Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sum type info in suggestions DB #3422

Merged
merged 10 commits into from
May 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
- [Fixed execution of defaulted arguments of Atom Constructors][3358]
- [Converting Enso Date to java.time.LocalDate and back][3374]
- [Functions with all-defaulted arguments now execute automatically][3414]
- [Provide `tagValues` for function arguments in the language server][3422]
- [Delay construction of Truffle nodes to speed initialization][3429]
- [Frgaal compiler integration to allow for latest Java constructs][3421]

Expand All @@ -202,6 +203,7 @@
[3412]: https://github.com/enso-org/enso/pull/3412
[3414]: https://github.com/enso-org/enso/pull/3414
[3417]: https://github.com/enso-org/enso/pull/3417
[3422]: https://github.com/enso-org/enso/pull/3422
[3429]: https://github.com/enso-org/enso/pull/3429
[3421]: https://github.com/enso-org/enso/pull/3421

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
}
],
"returnType" : "MyAtom",
Expand Down Expand Up @@ -141,14 +142,16 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "MyType",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "foo",
"reprType" : "Number",
"isSuspended" : false,
"hasDefault" : true,
"defaultValue" : "42"
"defaultValue" : "42",
"tagValues" : null
}
],
"selfType" : "MyType",
Expand Down Expand Up @@ -224,21 +227,24 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "b",
"reprType" : "Any",
"isSuspended" : true,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "c",
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : true,
"defaultValue" : "C"
"defaultValue" : "C",
"tagValues" : null
}
],
"returnType" : "IO",
Expand Down Expand Up @@ -356,21 +362,24 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "b",
"reprType" : "Any",
"isSuspended" : true,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "c",
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : true,
"defaultValue" : "C"
"defaultValue" : "C",
"tagValues" : null
}
],
"returnType" : "IO",
Expand Down Expand Up @@ -398,7 +407,8 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
}
],
"returnType" : "MyAtom",
Expand Down Expand Up @@ -461,14 +471,16 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "MyType",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "foo",
"reprType" : "Number",
"isSuspended" : false,
"hasDefault" : true,
"defaultValue" : "42"
"defaultValue" : "42",
"tagValues" : null
}
],
"selfType" : "MyType",
Expand Down Expand Up @@ -572,7 +584,8 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : true,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ object Suggestion {
reprType: String,
isSuspended: Boolean,
hasDefault: Boolean,
defaultValue: Option[String]
defaultValue: Option[String],
tagValues: Option[Seq[String]] = None
) extends ToLogString {

/** @inheritdoc */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ sealed trait Tree[+A] {
final def map[B](f: A => B): Tree[B] =
Tree.map(this)(f)

/** Finds the first element of the tree for which the given partial function
* is defined, and applies the partial function to it.
*
* @param f the partial function to apply
* @return the result of running `f` on the first element it's defined for.
*/
@JsonIgnore
final def collectFirst[B](f: PartialFunction[A, B]): Option[B] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some documentation

Tree.collectFirst(this)(f)

/** Selects all elements which satisfy a predicate.
*
* @param p the predicate used to test elements
Expand Down Expand Up @@ -208,6 +218,22 @@ object Tree {
Node(f(a), cx.map(mapNode(_)(f)))
}

private def collectFirst[A, B](
tree: Tree[A]
)(f: PartialFunction[A, B]): Option[B] = {
def collectFirstNode(node: Tree.Node[A]): Option[B] = {
if (f.isDefinedAt(node.element)) {
Some(f(node.element))
} else {
node.children.collectFirst((collectFirstNode _).unlift)
}
}
tree match {
case Root(c) => c.collectFirst((collectFirstNode _).unlift)
case n: Node[A] => collectFirstNode(n)
}
}

private def filter[A](tree: Tree[A])(p: A => Boolean): Tree[A] = {
def filterNode(node: Tree.Node[A]): Option[Tree.Node[A]] = {
val childrenFiltered = node.children.flatMap(filterNode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class RuntimeStubsGenerator() {
BindingAnalysis,
"Non-parsed module used in stubs generator"
)
localBindings.types.foreach { tp =>
localBindings.constructors.foreach { tp =>
val constructor = new AtomConstructor(tp.name, scope)
scope.registerConstructor(constructor)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,13 +336,22 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
resolvedName match {
case BindingsMap.ResolvedModule(module) =>
Some(module.getName)
case BindingsMap.ResolvedConstructor(module, cons) =>
Some(module.getName.createChild(cons.name))
case cons: BindingsMap.ResolvedConstructor =>
Some(cons.qualifiedName)
case _ =>
None
}
}

private def buildResolvedUnionTypeName(
resolvedName: BindingsMap.ResolvedTypeName
): Option[TypeArg] = resolvedName match {
case tp: BindingsMap.ResolvedType =>
Some(TypeArg.Sum(tp.qualifiedName, tp.getVariants.map(_.qualifiedName)))
case other: BindingsMap.ResolvedName =>
buildResolvedTypeName(other).map(TypeArg.Value)
}

/** Build type signature from the ir metadata.
*
* @param typeSignature the type signature metadata
Expand Down Expand Up @@ -380,19 +389,18 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
args :++ arg
case IR.Function.Lambda(List(targ), body, _, _, _, _) =>
val typeName = targ.name.name
val qualifiedTypeName = resolveTypeName(bindings, typeName)
.getOrElse(QualifiedName.simpleName(typeName))
val tdef = TypeArg.Value(qualifiedTypeName)
val tdef = resolveTypeName(bindings, typeName)
.getOrElse(TypeArg.Value(QualifiedName.simpleName(typeName)))
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)
.getOrElse(QualifiedName.simpleName(typeName))
args :+ TypeArg.Value(qualifiedTypeName)
val tdef = resolveTypeName(bindings, typeName)
.getOrElse(TypeArg.Value(QualifiedName.simpleName(typeName)))
args :+ tdef
case _ =>
args
}
Expand All @@ -415,10 +423,10 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
private def resolveTypeName(
bindings: Option[BindingAnalysis.Metadata],
name: String
): Option[QualifiedName] = {
): Option[TypeArg] = {
bindings
.flatMap(_.resolveUppercaseName(name).toOption)
.flatMap(buildResolvedTypeName)
.flatMap(_.resolveTypeName(name).toOption)
.flatMap(buildResolvedUnionTypeName)
}

/** Build arguments of a method.
Expand Down Expand Up @@ -521,7 +529,11 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
reprType = buildTypeArgumentName(targ),
isSuspended = varg.suspended,
hasDefault = varg.defaultValue.isDefined,
defaultValue = varg.defaultValue.flatMap(buildDefaultValue)
defaultValue = varg.defaultValue.flatMap(buildDefaultValue),
tagValues = targ match {
case TypeArg.Sum(_, variants) => Some(variants.map(_.toString))
case _ => None
}
)

/** Build the name of type argument.
Expand Down Expand Up @@ -549,6 +561,7 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
val argsList = args.map(go(_, level + 1)).mkString(" ")
val typeName = s"$funText $argsList"
if (level > 0) s"($typeName)" else typeName
case TypeArg.Sum(n, _) => n.toString
}

go(targ, 0)
Expand Down Expand Up @@ -639,6 +652,13 @@ object SuggestionBuilder {
sealed private trait TypeArg
private object TypeArg {

/** A sum type – one of many possible options.
* @param name the qualified name of the type.
* @param variants the qualified names of constituent atoms.
*/
case class Sum(name: QualifiedName, variants: Seq[QualifiedName])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation

extends TypeArg

/** Type with the name, like `A`.
*
* @param name the name of the type
Expand Down
Loading