diff --git a/engine/runtime/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala b/engine/runtime/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala index 5be02ae034b4..0d9409fb6c40 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala @@ -330,6 +330,10 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) { .getOrElse(QualifiedName.simpleName(typeName)) val tdef = TypeArg.Value(qualifiedTypeName) go(body, args :+ tdef) + case IR.Application.Prefix(tfun, targs, _, _, _, _) => + val appFunction = go(tfun, Vector()).head + val appArgs = targs.flatMap(arg => go(arg.value, Vector())) + args :+ TypeArg.Application(appFunction, appArgs.toVector) case tname: IR.Name => val typeName = tname.name val qualifiedTypeName = resolveTypeName(bindings, typeName) @@ -468,11 +472,20 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) { def go(targ: TypeArg, level: Int): String = targ match { case TypeArg.Value(name) => name.toString + case TypeArg.Function(Vector(typeArg)) => + val typeName = go(typeArg, level) + if (level > 0) s"($typeName)" else typeName case TypeArg.Function(types) => val typeList = types.map(go(_, level + 1)) if (level > 0) typeList.mkString("(", " -> ", ")") else typeList.mkString(" -> ") + case TypeArg.Application(fun, args) => + val funText = go(fun, level) + val argsList = args.map(go(_, level + 1)).mkString(" ") + val typeName = s"$funText $argsList" + if (level > 0) s"($typeName)" else typeName } + go(targ, 0) } @@ -570,6 +583,16 @@ object SuggestionBuilder { */ case class Function(signature: Vector[TypeArg]) extends TypeArg + /** Function application, like `Either A B`. + * + * @param function the function type + * @param arguments the list of argument types + */ + case class Application( + function: TypeArg, + arguments: Vector[TypeArg] + ) extends TypeArg + } val Any: String = "Builtins.Main.Any" diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/context/SuggestionBuilderTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/context/SuggestionBuilderTest.scala index a2eb06f1716b..a4d13b0545df 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/context/SuggestionBuilderTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/context/SuggestionBuilderTest.scala @@ -120,6 +120,135 @@ class SuggestionBuilderTest extends CompilerTest { ) } + "build method with a qualified type" in { + implicit val moduleContext: ModuleContext = freshModuleContext + + val code = + """ + |foo : Foo.Bar + |foo = 42""".stripMargin + val module = code.preprocessModule + + build(code, module) shouldEqual Tree.Root( + Vector( + ModuleAtomNode, + Tree.Node( + Suggestion.Method( + externalId = None, + module = "Unnamed.Test", + name = "foo", + arguments = Seq( + Suggestion.Argument("this", "Unnamed.Test", false, false, None) + ), + selfType = "Unnamed.Test", + returnType = "Foo.Bar", + documentation = None + ), + Vector() + ) + ) + ) + } + + "build method with an argument" in { + implicit val moduleContext: ModuleContext = freshModuleContext + + val code = + """ + |foo : Text -> Number + |foo a = 42""".stripMargin + val module = code.preprocessModule + + build(code, module) shouldEqual Tree.Root( + Vector( + ModuleAtomNode, + Tree.Node( + Suggestion.Method( + externalId = None, + module = "Unnamed.Test", + name = "foo", + arguments = Seq( + Suggestion.Argument("this", "Unnamed.Test", false, false, None), + Suggestion.Argument("a", "Text", false, false, None) + ), + selfType = "Unnamed.Test", + returnType = "Number", + documentation = None + ), + Vector() + ) + ) + ) + } + + "build method with a type containing higher kinds" in { + implicit val moduleContext: ModuleContext = freshModuleContext + + val code = + """ + |foo : Either (Vector Number) Text -> Number + |foo a = 42""".stripMargin + val module = code.preprocessModule + + build(code, module) shouldEqual Tree.Root( + Vector( + ModuleAtomNode, + Tree.Node( + Suggestion.Method( + externalId = None, + module = "Unnamed.Test", + name = "foo", + arguments = Seq( + Suggestion.Argument("this", "Unnamed.Test", false, false, None), + Suggestion.Argument( + "a", + "Either (Vector Number) Text", + false, + false, + None + ) + ), + selfType = "Unnamed.Test", + returnType = "Number", + documentation = None + ), + Vector() + ) + ) + ) + } + + "build method with a type containing qualified higher kinds" in { + pending // issue #1711 + implicit val moduleContext: ModuleContext = freshModuleContext + + val code = + """ + |foo : Foo.Bar Baz + |foo = 42""".stripMargin + val module = code.preprocessModule + + build(code, module) shouldEqual Tree.Root( + Vector( + ModuleAtomNode, + Tree.Node( + Suggestion.Method( + externalId = None, + module = "Unnamed.Test", + name = "foo", + arguments = Seq( + Suggestion.Argument("this", "Unnamed.Test", false, false, None) + ), + selfType = "Unnamed.Test", + returnType = "Foo.Bar Baz", + documentation = None + ), + Vector() + ) + ) + ) + } + "build method with complex body" in { implicit val moduleContext: ModuleContext = freshModuleContext