diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Any.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Any.java index 693dbe290223..87a10fb07b3d 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Any.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Any.java @@ -10,7 +10,7 @@ public Class getSuperType() { } @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Builtin.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Builtin.java index c4cb8322a085..c0d314685f60 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Builtin.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Builtin.java @@ -74,7 +74,7 @@ public final void initialize(EnsoLanguage language, ModuleScope scope, Map 0; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Error.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Error.java index a3c7b3e80a83..690ae5846424 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Error.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Error.java @@ -10,7 +10,7 @@ protected Class getSuperType() { } @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Nothing.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Nothing.java index 55870ea64ddb..a62815bcc712 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Nothing.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/Nothing.java @@ -5,7 +5,7 @@ @BuiltinType(name = "Standard.Base.Nothing.Nothing") public class Nothing extends Builtin { @Override - protected boolean containsValues() { + public boolean containsValues() { return false; } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/Panic.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/Panic.java index d6a62e4c23c1..7ddffad71851 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/Panic.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/Panic.java @@ -6,7 +6,7 @@ @BuiltinType(name = "Standard.Base.Panic.Panic") public class Panic extends Builtin { @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/function/Function.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/function/Function.java index 6813e1be9e2a..b08fd89f5108 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/function/Function.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/function/Function.java @@ -6,7 +6,7 @@ @BuiltinType(name = "Standard.Base.Function.Function") public class Function extends Builtin { @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Decimal.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Decimal.java index 45ec98234453..ba60fee6cddc 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Decimal.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Decimal.java @@ -11,7 +11,7 @@ protected Class getSuperType() { } @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Integer.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Integer.java index 54fabd914b98..296f7521dc95 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Integer.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Integer.java @@ -11,7 +11,7 @@ protected Class getSuperType() { } @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Number.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Number.java index 35af558bde48..d09c5c674068 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Number.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/number/Number.java @@ -6,7 +6,7 @@ @BuiltinType(name = "Standard.Base.Data.Numbers.Number") public class Number extends Builtin { @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/Text.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/Text.java index 5e2e2cd69f4f..80aa8f8471e8 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/Text.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/Text.java @@ -6,7 +6,7 @@ @BuiltinType(name = "Standard.Base.Data.Text.Text") public class Text extends Builtin { @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala b/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala index 493bb005f246..b14d5dfe67a1 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala @@ -238,7 +238,7 @@ final class SerializationManager( compiler.packageRepository .getModulesForLibrary(libraryName) .flatMap { module => - SuggestionBuilder(module) + SuggestionBuilder(module, compiler) .build(module.getName, module.getIr) .toVector .filter(Suggestion.isGlobal) 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 e4fe4095ed11..7ae22e757c03 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 @@ -1,5 +1,6 @@ package org.enso.compiler.context +import org.enso.compiler.Compiler import org.enso.compiler.core.IR import org.enso.compiler.data.BindingsMap import org.enso.compiler.pass.resolve.{ @@ -26,7 +27,8 @@ import scala.collection.mutable */ final class SuggestionBuilder[A: IndexedSource]( val source: A, - val typeGraph: TypeGraph + val typeGraph: TypeGraph, + val compiler: Compiler ) { import SuggestionBuilder._ @@ -379,21 +381,43 @@ final class SuggestionBuilder[A: IndexedSource]( ) } - private def buildResolvedUnionTypeName( + /** Build a [[TypeArg]] from the resolved type name. + * + * @param resolvedName the resolved type name + * @return the corresponding type argument + */ + private def buildResolvedTypeName( resolvedName: BindingsMap.ResolvedName - ): TypeArg = resolvedName match { - case tp: BindingsMap.ResolvedType => - if (tp.getVariants.size > 1) { - TypeArg.Sum( - Some(tp.qualifiedName), - tp.getVariants.map(r => TypeArg.Value(r.qualifiedName)) - ) - } else { - TypeArg.Sum(Some(tp.qualifiedName), Seq.empty) - } - case _: BindingsMap.ResolvedName => - TypeArg.Value(resolvedName.qualifiedName) - } + ): TypeArg = + resolvedName match { + case tp: BindingsMap.ResolvedType => + tp.getVariants.size match { + case 0 => + val isBuiltinTypeWithValues = + tp.tp.builtinType && + Option(compiler.builtins.getBuiltinType(tp.tp.name)) + .exists(_.containsValues()) + if (isBuiltinTypeWithValues) { + TypeArg.Sum(Some(tp.qualifiedName), Seq()) + } else { + TypeArg.Sum( + Some(tp.qualifiedName), + Seq(TypeArg.Value(tp.qualifiedName)) + ) + } + + case 1 => + TypeArg.Sum(Some(tp.qualifiedName), Seq()) + + case _ => + TypeArg.Sum( + Some(tp.qualifiedName), + tp.getVariants.map(r => TypeArg.Value(r.qualifiedName)) + ) + } + case _: BindingsMap.ResolvedName => + TypeArg.Value(resolvedName.qualifiedName) + } /** Build type signature from the ir metadata. * @@ -437,7 +461,7 @@ final class SuggestionBuilder[A: IndexedSource]( case tname: IR.Name => tname .getMetadata(TypeNames) - .map(t => buildResolvedUnionTypeName(t.target)) + .map(t => buildResolvedTypeName(t.target)) .getOrElse(TypeArg.Value(QualifiedName.simpleName(tname.name))) case _ => @@ -551,24 +575,29 @@ final class SuggestionBuilder[A: IndexedSource]( isSuspended = varg.suspended, hasDefault = varg.defaultValue.isDefined, defaultValue = varg.defaultValue.flatMap(buildDefaultValue), - tagValues = targ match { - case s: TypeArg.Sum => { - val tagValues = pluckVariants(s) - if (tagValues.nonEmpty) { - Some(tagValues) - } else { - None - } - } - case _ => None - } + tagValues = buildTagValues(targ) ) - private def pluckVariants(arg: TypeArg): Seq[String] = arg match { - case TypeArg.Sum(_, List()) => Seq() - case TypeArg.Sum(_, variants) => variants.flatMap(pluckVariants) - case TypeArg.Value(n) => Seq(n.toString) - case _ => Seq() + /** Build tag values of type argument. + * + * @param targ the type argument + * @return the list of tag values + */ + private def buildTagValues(targ: TypeArg): Option[Seq[String]] = { + def go(arg: TypeArg): Seq[String] = arg match { + case TypeArg.Sum(_, List()) => Seq() + case TypeArg.Sum(_, variants) => variants.flatMap(go) + case TypeArg.Value(n) => Seq(n.toString) + case _ => Seq() + } + + targ match { + case s: TypeArg.Sum => + val tagValues = go(s) + Option.unless(tagValues.isEmpty)(tagValues) + case _ => None + + } } /** Build the name of type argument. @@ -661,8 +690,11 @@ object SuggestionBuilder { * @param module the module to index * @return the suggestions builder for the module */ - def apply(module: Module): SuggestionBuilder[CharSequence] = - SuggestionBuilder(module.getSource.getCharacters) + def apply( + module: Module, + compiler: Compiler + ): SuggestionBuilder[CharSequence] = + SuggestionBuilder(module.getSource.getCharacters, compiler) /** Create the suggestion builder. * @@ -672,17 +704,21 @@ object SuggestionBuilder { */ def apply[A: IndexedSource]( source: A, - typeGraph: TypeGraph + typeGraph: TypeGraph, + compiler: Compiler ): SuggestionBuilder[A] = - new SuggestionBuilder[A](source, typeGraph) + new SuggestionBuilder[A](source, typeGraph, compiler) /** Create the suggestion builder. * * @param source the text source * @tparam A the type of the text source */ - def apply[A: IndexedSource](source: A): SuggestionBuilder[A] = - new SuggestionBuilder[A](source, Types.getTypeHierarchy) + def apply[A: IndexedSource]( + source: A, + compiler: Compiler + ): SuggestionBuilder[A] = + new SuggestionBuilder[A](source, Types.getTypeHierarchy, compiler) /** A single level of an `IR`. * @@ -722,7 +758,7 @@ object SuggestionBuilder { /** Function type, like `A -> A`. * - * @param signature the list of types defining the function + * @param arguments the list of types defining the function */ case class Function(arguments: Vector[TypeArg], result: TypeArg) extends TypeArg diff --git a/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/AnalyzeModuleInScopeJob.scala b/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/AnalyzeModuleInScopeJob.scala index 3205c07103fd..b6aa2f7ef8b7 100644 --- a/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/AnalyzeModuleInScopeJob.scala +++ b/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/AnalyzeModuleInScopeJob.scala @@ -44,9 +44,10 @@ final class AnalyzeModuleInScopeJob( ctx.executionService.getLogger .log(Level.FINEST, s"Analyzing module in scope ${module.getName}") val moduleName = module.getName - val newSuggestions = SuggestionBuilder(module.getSource.getCharacters) - .build(moduleName, module.getIr) - .filter(Suggestion.isGlobal) + val newSuggestions = + SuggestionBuilder(module, ctx.executionService.getContext.getCompiler) + .build(moduleName, module.getIr) + .filter(Suggestion.isGlobal) val prevExports = ModuleExports(moduleName.toString, Set()) val newExports = exportsBuilder.build(module.getName, module.getIr) val notification = Api.SuggestionsDatabaseModuleUpdateNotification( diff --git a/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/AnalyzeModuleJob.scala b/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/AnalyzeModuleJob.scala index 76d96f0c094c..d6cfed5bd6e0 100644 --- a/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/AnalyzeModuleJob.scala +++ b/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/AnalyzeModuleJob.scala @@ -51,13 +51,15 @@ object AnalyzeModuleJob { changeset: Changeset[Rope] )(implicit ctx: RuntimeContext): Unit = { val moduleName = module.getName + val compiler = ctx.executionService.getContext.getCompiler if (module.isIndexed) { ctx.executionService.getLogger .log(Level.FINEST, s"Analyzing indexed module $moduleName") - val prevSuggestions = SuggestionBuilder(changeset.source) - .build(moduleName, changeset.ir) + val prevSuggestions = + SuggestionBuilder(changeset.source, compiler) + .build(moduleName, changeset.ir) val newSuggestions = - SuggestionBuilder(module.getSource.getCharacters) + SuggestionBuilder(module, compiler) .build(moduleName, module.getIr) val diff = SuggestionDiff .compute(prevSuggestions, newSuggestions) @@ -75,7 +77,7 @@ object AnalyzeModuleJob { ctx.executionService.getLogger .log(Level.FINEST, s"Analyzing not-indexed module ${module.getName}") val newSuggestions = - SuggestionBuilder(module.getSource.getCharacters) + SuggestionBuilder(module, compiler) .build(moduleName, module.getIr) val prevExports = ModuleExports(moduleName.toString, Set()) val newExports = exportsBuilder.build(moduleName, module.getIr) 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 368e026674bf..f5eccc34261a 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 @@ -615,6 +615,7 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers { Some( Seq( "Number", + "Unnamed.Test.Other_Atom", "Unnamed.Test.My_Atom.Variant_1", "Unnamed.Test.My_Atom.Variant_2" ) @@ -632,6 +633,107 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers { ) } + "build argument tag values" in { + + val code = + """import Standard.Base.Data.Text.Text + |import Standard.Base.Data.Boolean.Boolean + | + |type Value + | A + | B + | + |type Auto + | + |foo : Text | Boolean | Value | Auto -> Any + |foo a = a + |""".stripMargin + val module = code.preprocessModule + + build(code, module) shouldEqual Tree.Root( + Vector( + ModuleNode, + Tree.Node( + Suggestion.Type( + externalId = None, + module = "Unnamed.Test", + name = "Value", + params = Seq(), + returnType = "Unnamed.Test.Value", + parentType = Some(SuggestionBuilder.Any), + documentation = None + ), + Vector() + ), + Tree.Node( + Suggestion.Constructor( + externalId = None, + module = "Unnamed.Test", + name = "A", + arguments = Seq(), + returnType = "Unnamed.Test.Value", + documentation = None + ), + Vector() + ), + Tree.Node( + Suggestion.Constructor( + externalId = None, + module = "Unnamed.Test", + name = "B", + arguments = Seq(), + returnType = "Unnamed.Test.Value", + documentation = None + ), + Vector() + ), + Tree.Node( + Suggestion.Type( + externalId = None, + module = "Unnamed.Test", + name = "Auto", + params = Seq(), + returnType = "Unnamed.Test.Auto", + parentType = Some(SuggestionBuilder.Any), + documentation = None + ), + Vector() + ), + Tree.Node( + Suggestion.Method( + externalId = None, + module = "Unnamed.Test", + name = "foo", + arguments = Seq( + Suggestion.Argument("self", "Unnamed.Test", false, false, None), + Suggestion.Argument( + "a", + "Standard.Base.Data.Text.Text | Standard.Base.Data.Boolean.Boolean | Unnamed.Test.Value | Unnamed.Test.Auto", + false, + false, + None, + Some( + Seq( + "Standard.Base.Data.Boolean.Boolean.True", + "Standard.Base.Data.Boolean.Boolean.False", + "Unnamed.Test.Value.A", + "Unnamed.Test.Value.B", + "Unnamed.Test.Auto" + ) + ) + ) + ), + selfType = "Unnamed.Test", + returnType = "Any", + isStatic = true, + documentation = None + ), + Vector() + ) + ) + ) + } + "build method with lazy arguments" in { val code = @@ -699,7 +801,7 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers { false, false, None, - None + Some(Seq("Unnamed.Test.A")) ) ), selfType = "Unnamed.Test", @@ -1123,7 +1225,7 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers { false, false, None, - None + Some(Seq("Unnamed.Test.A")) ) ), returnType = "Unnamed.Test.A", @@ -2598,5 +2700,5 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers { ir: IR.Module, module: QualifiedName = Module ): Tree.Root[Suggestion] = - SuggestionBuilder(source).build(module, ir) + SuggestionBuilder(source, langCtx.getCompiler).build(module, ir) } diff --git a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java index 424c76018fed..a6508d59db52 100644 --- a/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java +++ b/lib/scala/interpreter-dsl/src/main/java/org/enso/interpreter/dsl/BuiltinsProcessor.java @@ -108,7 +108,7 @@ private void generateBuiltinType( out.println("public class " + builtinType.name() + " extends Builtin {"); out.println(""" @Override - protected boolean containsValues() { + public boolean containsValues() { return true; } }