Support Types Unions in Suggestions Database (#1912)

Add support for binary operators in type signatures
This commit is contained in:
Dmitry Bushev 2021-07-30 17:58:33 +03:00 committed by GitHub
parent bba5ab4a7d
commit 6bfd500846
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 5 deletions

View File

@ -335,9 +335,12 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
): Vector[TypeArg] = {
def go(typeExpr: IR.Expression, args: Vector[TypeArg]): Vector[TypeArg] =
typeExpr match {
case IR.Application.Operator.Binary(left, _, right, _, _, _) =>
val arg = TypeArg.Function(go(left.value, Vector()))
go(right.value, args :+ arg)
case IR.Application.Operator.Binary(left, op, right, _, _, _) =>
val arg = for {
leftArg <- go(left.value, Vector()).headOption
rightArg <- go(right.value, Vector()).headOption
} yield TypeArg.Binary(leftArg, rightArg, op.name)
args :++ arg
case IR.Function.Lambda(List(targ), body, _, _, _, _) =>
val typeName = targ.name.name
val qualifiedTypeName = resolveTypeName(bindings, typeName)
@ -357,7 +360,13 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
args
}
go(typeExpr, Vector())
typeExpr match {
case IR.Application.Operator.Binary(left, _, right, _, _, _) =>
val arg = TypeArg.Function(go(left.value, Vector()))
go(right.value, Vector(arg))
case expr =>
go(expr, Vector())
}
}
/** Resolve unqualified type name.
@ -494,6 +503,10 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
val typeList = types.map(go(_, level + 1))
if (level > 0) typeList.mkString("(", " -> ", ")")
else typeList.mkString(" -> ")
case TypeArg.Binary(l, r, op) =>
val left = go(l, level + 1)
val right = go(r, level + 1)
s"$left $op $right"
case TypeArg.Application(fun, args) =>
val funText = go(fun, level)
val argsList = args.map(go(_, level + 1)).mkString(" ")
@ -598,6 +611,15 @@ object SuggestionBuilder {
*/
case class Function(signature: Vector[TypeArg]) extends TypeArg
/** Binary operator, like `A | B`
*
* @param left the left hand side of a binary operator
* @param right the right hand side of a binary operator
* @param operator the binary operator
*/
case class Binary(left: TypeArg, right: TypeArg, operator: String)
extends TypeArg
/** Function application, like `Either A B`.
*
* @param function the function type

View File

@ -518,6 +518,59 @@ class SuggestionBuilderTest extends CompilerTest {
)
}
"build method with union type signature" in {
implicit val moduleContext: ModuleContext = freshModuleContext
val code =
"""type MyAtom
|
|MyAtom.apply : (Number | Text | MyAtom) -> Number
|MyAtom.apply f = f this
|""".stripMargin
val module = code.preprocessModule
build(code, module) shouldEqual Tree.Root(
Vector(
ModuleNode,
Tree.Node(
Suggestion.Atom(
externalId = None,
module = "Unnamed.Test",
name = "MyAtom",
arguments = Seq(),
returnType = "Unnamed.Test.MyAtom",
documentation = None,
documentationHtml = None
),
Vector()
),
Tree.Node(
Suggestion.Method(
externalId = None,
module = "Unnamed.Test",
name = "apply",
arguments = Seq(
Suggestion
.Argument("this", "Unnamed.Test.MyAtom", false, false, None),
Suggestion.Argument(
"f",
"Number | Text | Unnamed.Test.MyAtom",
false,
false,
None
)
),
selfType = "Unnamed.Test.MyAtom",
returnType = "Number",
documentation = None,
documentationHtml = None
),
Vector()
)
)
)
}
"build method with lazy arguments" in {
implicit val moduleContext: ModuleContext = freshModuleContext

View File

@ -264,5 +264,5 @@ object SuggestionsVersion extends TableQuery(new SuggestionsVersionTable(_))
object SchemaVersion extends TableQuery(new SchemaVersionTable(_)) {
/** The current schema version. */
val CurrentVersion: Long = 4
val CurrentVersion: Long = 5
}