mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 20:11:36 +03:00
Put all reexports of given entry in Suggestion Database (#9454)
close #9351 Changelog: - update: deprecate the `reexport` suggestion field - add: `reexports` suggestion field containing the list of modules re-exporting this symbol - update: exports logic to gather all the symbols exported from a given module
This commit is contained in:
parent
09a6ab7bd6
commit
fb0559e7ab
@ -500,8 +500,14 @@ interface Module {
|
||||
/** The documentation string. */
|
||||
documentation?: string;
|
||||
|
||||
/** The fully qualified module name re-exporting this module. */
|
||||
/** The fully qualified module name re-exporting this module.
|
||||
*
|
||||
* @deprecated use reexports field instead
|
||||
*/
|
||||
reexport?: string;
|
||||
|
||||
/** The list of fully qualified module names re-exporting this module. */
|
||||
reexports: string[];
|
||||
}
|
||||
|
||||
interface Type {
|
||||
@ -520,9 +526,15 @@ interface Type {
|
||||
/** Qualified name of the parent type. */
|
||||
parentType?: string;
|
||||
|
||||
/** The fully qualified module name re-exporting this type. */
|
||||
/** The fully qualified module name re-exporting this type.
|
||||
*
|
||||
* @deprecated use reexports field instead
|
||||
*/
|
||||
reexport?: string;
|
||||
|
||||
/** The list of fully qualified module names re-exporting this type. */
|
||||
reexports: string[];
|
||||
|
||||
/** The documentation string. */
|
||||
documentation?: string;
|
||||
}
|
||||
@ -543,9 +555,15 @@ interface Constructor {
|
||||
/** The type of the constructor. */
|
||||
returnType: string;
|
||||
|
||||
/** The fully qualified module name re-exporting this constructor. */
|
||||
/** The fully qualified module name re-exporting this constructor.
|
||||
*
|
||||
* @deprecated use reexports field instead
|
||||
*/
|
||||
reexport?: string;
|
||||
|
||||
/** The list of fully qualified module names re-exporting this constructor. */
|
||||
reexports: string[];
|
||||
|
||||
/** The documentation string. */
|
||||
documentation?: string;
|
||||
|
||||
@ -575,9 +593,15 @@ interface Method {
|
||||
/** The flag indicating whether this method is static or instance. */
|
||||
isStatic: boolean;
|
||||
|
||||
/** The fully qualified module name re-exporting this method. */
|
||||
/** The fully qualified module name re-exporting this method.
|
||||
*
|
||||
* @deprecated use reexports field instead
|
||||
*/
|
||||
reexport?: string;
|
||||
|
||||
/** The list of fully qualified module names re-exporting this method. */
|
||||
reexports: string[];
|
||||
|
||||
/** The documentation string. */
|
||||
documentation?: string;
|
||||
|
||||
|
@ -33,6 +33,8 @@ object SearchProtocol {
|
||||
val Documentation = "documentation"
|
||||
|
||||
val Reexport = "reexport"
|
||||
|
||||
val Reexports = "reexports"
|
||||
}
|
||||
|
||||
private object CodecType {
|
||||
@ -64,7 +66,12 @@ object SearchProtocol {
|
||||
case module: Suggestion.Module =>
|
||||
Encoder[Suggestion.Module]
|
||||
.apply(module)
|
||||
.deepMerge(Json.obj(CodecField.Type -> SuggestionType.Module.asJson))
|
||||
.deepMerge(
|
||||
Json.obj(
|
||||
CodecField.Type -> SuggestionType.Module.asJson,
|
||||
CodecField.Reexport -> module.reexports.headOption.asJson
|
||||
)
|
||||
)
|
||||
|
||||
case tpe: Suggestion.Type =>
|
||||
Encoder[Suggestion.Type]
|
||||
@ -72,7 +79,8 @@ object SearchProtocol {
|
||||
.deepMerge(
|
||||
Json.obj(
|
||||
CodecField.Type -> SuggestionType.Type.asJson,
|
||||
CodecField.ReturnType -> Json.Null
|
||||
CodecField.ReturnType -> Json.Null,
|
||||
CodecField.Reexport -> tpe.reexports.headOption.asJson
|
||||
)
|
||||
)
|
||||
.dropNullValues
|
||||
@ -81,7 +89,10 @@ object SearchProtocol {
|
||||
Encoder[Suggestion.Constructor]
|
||||
.apply(constructor)
|
||||
.deepMerge(
|
||||
Json.obj(CodecField.Type -> SuggestionType.Constructor.asJson)
|
||||
Json.obj(
|
||||
CodecField.Type -> SuggestionType.Constructor.asJson,
|
||||
CodecField.Reexport -> constructor.reexports.headOption.asJson
|
||||
)
|
||||
)
|
||||
.dropNullValues
|
||||
|
||||
@ -89,7 +100,10 @@ object SearchProtocol {
|
||||
Encoder[Suggestion.DefinedMethod]
|
||||
.apply(conversionToMethod(conversion))
|
||||
.deepMerge(
|
||||
Json.obj(CodecField.Type -> SuggestionType.Method.asJson)
|
||||
Json.obj(
|
||||
CodecField.Type -> SuggestionType.Method.asJson,
|
||||
CodecField.Reexport -> conversion.reexports.headOption.asJson
|
||||
)
|
||||
)
|
||||
.dropNullValues
|
||||
|
||||
@ -97,7 +111,10 @@ object SearchProtocol {
|
||||
Encoder[Suggestion.DefinedMethod]
|
||||
.apply(getterToMethod(getter))
|
||||
.deepMerge(
|
||||
Json.obj(CodecField.Type -> SuggestionType.Method.asJson)
|
||||
Json.obj(
|
||||
CodecField.Type -> SuggestionType.Method.asJson,
|
||||
CodecField.Reexport -> getter.reexports.headOption.asJson
|
||||
)
|
||||
)
|
||||
.dropNullValues
|
||||
|
||||
@ -105,7 +122,10 @@ object SearchProtocol {
|
||||
Encoder[Suggestion.DefinedMethod]
|
||||
.apply(method)
|
||||
.deepMerge(
|
||||
Json.obj(CodecField.Type -> SuggestionType.Method.asJson)
|
||||
Json.obj(
|
||||
CodecField.Type -> SuggestionType.Method.asJson,
|
||||
CodecField.Reexport -> method.reexports.headOption.asJson
|
||||
)
|
||||
)
|
||||
.dropNullValues
|
||||
|
||||
@ -137,7 +157,7 @@ object SearchProtocol {
|
||||
conversion.isStatic,
|
||||
conversion.documentation,
|
||||
conversion.annotations,
|
||||
conversion.reexport
|
||||
conversion.reexports
|
||||
)
|
||||
|
||||
private def getterToMethod(
|
||||
@ -153,7 +173,7 @@ object SearchProtocol {
|
||||
getter.isStatic,
|
||||
getter.documentation,
|
||||
getter.annotations,
|
||||
getter.reexport
|
||||
getter.reexports
|
||||
)
|
||||
|
||||
private val suggestionTypeDecoder: Decoder[Suggestion.Type] =
|
||||
@ -171,7 +191,7 @@ object SearchProtocol {
|
||||
documentation <- cursor
|
||||
.downField(CodecField.Documentation)
|
||||
.as[Option[String]]
|
||||
reexport <- cursor.downField(CodecField.Reexport).as[Option[String]]
|
||||
reexports <- cursor.downField(CodecField.Reexports).as[Set[String]]
|
||||
} yield {
|
||||
val returnType =
|
||||
QualifiedName.fromString(module).createChild(name).toString
|
||||
@ -183,7 +203,7 @@ object SearchProtocol {
|
||||
returnType,
|
||||
parentType,
|
||||
documentation,
|
||||
reexport
|
||||
reexports
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ final class SuggestionsHandler(
|
||||
for {
|
||||
actionResults <- suggestionsRepo.applyActions(msg.actions)
|
||||
treeResults <- suggestionsRepo.applyTree(msg.updates.toVector)
|
||||
exportResults <- suggestionsRepo.applyExports(msg.exports)
|
||||
exportResults <- suggestionsRepo.getExportedSymbols(msg.exports)
|
||||
version <- suggestionsRepo.currentVersion
|
||||
} yield {
|
||||
val actionUpdates = actionResults.flatMap {
|
||||
|
@ -642,7 +642,7 @@ class SuggestionsHandlerSpec
|
||||
DeliverToJsonController(
|
||||
clientId,
|
||||
SearchProtocol.SuggestionsDatabaseUpdateNotification(
|
||||
updates1.size.toLong + 1,
|
||||
updates1.size.toLong,
|
||||
updates2
|
||||
)
|
||||
)
|
||||
@ -690,7 +690,7 @@ class SuggestionsHandlerSpec
|
||||
DeliverToJsonController(
|
||||
clientId,
|
||||
SearchProtocol.SuggestionsDatabaseUpdateNotification(
|
||||
updates1.size.toLong + 2,
|
||||
updates1.size.toLong,
|
||||
updates3
|
||||
)
|
||||
)
|
||||
|
@ -65,7 +65,8 @@ class SuggestionsHandlerEventsTest
|
||||
"tagValues" : null
|
||||
}
|
||||
],
|
||||
"parentType" : "Any"
|
||||
"parentType" : "Any",
|
||||
"reexports" : []
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -117,7 +118,8 @@ class SuggestionsHandlerEventsTest
|
||||
],
|
||||
"returnType" : "MyAtom",
|
||||
"documentation" : " PRIVATE\n\n A key-value store. This type assumes all keys are pairwise comparable,\n using the `<`, `>` and `==` operators.\n\n Arguments:\n - one: The first.\n - two_three: The *second*.\n\n ? Info\n Here is a thing.",
|
||||
"annotations" : ["a"]
|
||||
"annotations" : ["a"],
|
||||
"reexports" : []
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -161,7 +163,8 @@ class SuggestionsHandlerEventsTest
|
||||
"selfType" : "MyType",
|
||||
"returnType" : "Any",
|
||||
"isStatic" : false,
|
||||
"annotations" : [ ]
|
||||
"annotations" : [ ],
|
||||
"reexports" : [ ]
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -232,7 +235,8 @@ class SuggestionsHandlerEventsTest
|
||||
"returnType" : "Number",
|
||||
"isStatic" : false,
|
||||
"documentation" : "Lovely",
|
||||
"annotations" : ["foo"]
|
||||
"annotations" : ["foo"],
|
||||
"reexports" : []
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -578,7 +582,7 @@ class SuggestionsHandlerEventsTest
|
||||
}
|
||||
}
|
||||
],
|
||||
"currentVersion" : 9
|
||||
"currentVersion" : 8
|
||||
}
|
||||
}
|
||||
""")
|
||||
@ -625,7 +629,7 @@ class SuggestionsHandlerEventsTest
|
||||
"id" : 6
|
||||
}
|
||||
],
|
||||
"currentVersion" : 9
|
||||
"currentVersion" : 8
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
@ -5,6 +5,8 @@ import org.enso.logger.masking.ToLogString
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
import scala.collection.immutable.ListSet
|
||||
|
||||
/** A search suggestion. */
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
@JsonSubTypes(
|
||||
@ -51,8 +53,7 @@ sealed trait Suggestion extends ToLogString {
|
||||
def returnType: String
|
||||
def documentation: Option[String]
|
||||
|
||||
/** Set the reexport field of the suggestion. */
|
||||
def withReexport(reexport: Option[String]): Suggestion
|
||||
def withReexports(reexports: Set[String]): Suggestion
|
||||
}
|
||||
|
||||
object Suggestion {
|
||||
@ -223,12 +224,12 @@ object Suggestion {
|
||||
*
|
||||
* @param module the fully qualified module name
|
||||
* @param documentation the documentation string
|
||||
* @param reexport the module re-exporting this module
|
||||
* @param reexports modules re-exporting this module
|
||||
*/
|
||||
case class Module(
|
||||
module: String,
|
||||
documentation: Option[String],
|
||||
reexport: Option[String] = None
|
||||
reexports: Set[String] = ListSet()
|
||||
) extends Suggestion
|
||||
with ToLogString {
|
||||
|
||||
@ -242,14 +243,14 @@ object Suggestion {
|
||||
module
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexport(reexport: Option[String]): Module =
|
||||
copy(reexport = reexport)
|
||||
override def withReexports(reexports: Set[String]): Suggestion =
|
||||
copy(reexports = reexports)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def toLogString(shouldMask: Boolean): String =
|
||||
s"Module(module=$module,name=$name,documentation=" +
|
||||
(if (shouldMask) documentation.map(_ => STUB) else documentation) +
|
||||
s",reexport=$reexport)"
|
||||
s",reexports=$reexports)"
|
||||
}
|
||||
|
||||
/** A type definition.
|
||||
@ -261,7 +262,7 @@ object Suggestion {
|
||||
* @param returnType the type of an atom
|
||||
* @param parentType qualified name of the parent type
|
||||
* @param documentation the documentation string
|
||||
* @param reexport the module re-exporting this atom
|
||||
* @param reexports modules re-exporting this atom
|
||||
*/
|
||||
case class Type(
|
||||
externalId: Option[ExternalID],
|
||||
@ -271,13 +272,13 @@ object Suggestion {
|
||||
returnType: String,
|
||||
parentType: Option[String],
|
||||
documentation: Option[String],
|
||||
reexport: Option[String] = None
|
||||
reexports: Set[String] = ListSet()
|
||||
) extends Suggestion
|
||||
with ToLogString {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexport(reexport: Option[String]): Type =
|
||||
copy(reexport = reexport)
|
||||
override def withReexports(reexports: Set[String]): Suggestion =
|
||||
copy(reexports = reexports)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def toLogString(shouldMask: Boolean): String =
|
||||
@ -290,7 +291,7 @@ object Suggestion {
|
||||
s"parentType=$parentType" +
|
||||
s",documentation=" + (if (shouldMask) documentation.map(_ => STUB)
|
||||
else documentation) +
|
||||
s",reexport=$reexport)"
|
||||
s",reexports=$reexports)"
|
||||
}
|
||||
|
||||
/** A value constructor.
|
||||
@ -302,7 +303,7 @@ object Suggestion {
|
||||
* @param returnType the type of an atom
|
||||
* @param documentation the documentation string
|
||||
* @param annotations the list of annotations
|
||||
* @param reexport the module re-exporting this atom
|
||||
* @param reexports modules re-exporting this atom
|
||||
*/
|
||||
case class Constructor(
|
||||
externalId: Option[ExternalID],
|
||||
@ -312,13 +313,13 @@ object Suggestion {
|
||||
returnType: String,
|
||||
documentation: Option[String],
|
||||
annotations: Seq[String],
|
||||
reexport: Option[String] = None
|
||||
reexports: Set[String] = ListSet()
|
||||
) extends Suggestion
|
||||
with ToLogString {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexport(reexport: Option[String]): Constructor =
|
||||
copy(reexport = reexport)
|
||||
override def withReexports(reexports: Set[String]): Suggestion =
|
||||
copy(reexports = reexports)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def toLogString(shouldMask: Boolean): String =
|
||||
@ -330,7 +331,7 @@ object Suggestion {
|
||||
s"returnType=$returnType" +
|
||||
s",documentation=" + (if (shouldMask) documentation.map(_ => STUB)
|
||||
else documentation) +
|
||||
s",reexport=$reexport)"
|
||||
s",reexports=$reexports)"
|
||||
}
|
||||
|
||||
/** Base trait for method suggestions. */
|
||||
@ -356,7 +357,7 @@ object Suggestion {
|
||||
def selfType: String
|
||||
def isStatic: Boolean
|
||||
def annotations: Seq[String]
|
||||
def reexport: Option[String]
|
||||
def reexports: Set[String]
|
||||
}
|
||||
|
||||
/** A method generated to access constructor field.
|
||||
@ -369,7 +370,7 @@ object Suggestion {
|
||||
* @param returnType the return type of a method
|
||||
* @param documentation the documentation string
|
||||
* @param annotations the list of annotations
|
||||
* @param reexport the module re-exporting this method
|
||||
* @param reexports modules re-exporting this method
|
||||
*/
|
||||
case class Getter(
|
||||
externalId: Option[ExternalID],
|
||||
@ -380,7 +381,7 @@ object Suggestion {
|
||||
returnType: String,
|
||||
documentation: Option[String],
|
||||
annotations: Seq[String],
|
||||
reexport: Option[String] = None
|
||||
reexports: Set[String] = ListSet()
|
||||
) extends Method
|
||||
with ToLogString {
|
||||
|
||||
@ -389,8 +390,8 @@ object Suggestion {
|
||||
override def isStatic: Boolean = false
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexport(reexport: Option[String]): Method =
|
||||
copy(reexport = reexport)
|
||||
override def withReexports(reexports: Set[String]): Suggestion =
|
||||
copy(reexports = reexports)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def toLogString(shouldMask: Boolean): String =
|
||||
@ -402,7 +403,7 @@ object Suggestion {
|
||||
s"returnType=$returnType," +
|
||||
s"documentation=" + (if (shouldMask) documentation.map(_ => STUB)
|
||||
else documentation) +
|
||||
s",reexport=$reexport)"
|
||||
s",reexports=$reexports)"
|
||||
}
|
||||
|
||||
/** A function defined on a type or a module.
|
||||
@ -416,7 +417,7 @@ object Suggestion {
|
||||
* @param isStatic the flag indicating whether a method is static or instance
|
||||
* @param documentation the documentation string
|
||||
* @param annotations the list of annotations
|
||||
* @param reexport the module re-exporting this method
|
||||
* @param reexports modules re-exporting this method
|
||||
*/
|
||||
case class DefinedMethod(
|
||||
externalId: Option[ExternalID],
|
||||
@ -428,13 +429,13 @@ object Suggestion {
|
||||
isStatic: Boolean,
|
||||
documentation: Option[String],
|
||||
annotations: Seq[String],
|
||||
reexport: Option[String] = None
|
||||
reexports: Set[String] = ListSet()
|
||||
) extends Method
|
||||
with ToLogString {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexport(reexport: Option[String]): Method =
|
||||
copy(reexport = reexport)
|
||||
override def withReexports(reexports: Set[String]): Suggestion =
|
||||
copy(reexports = reexports)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def toLogString(shouldMask: Boolean): String =
|
||||
@ -447,7 +448,7 @@ object Suggestion {
|
||||
s"isStatic=$isStatic," +
|
||||
s"documentation=" + (if (shouldMask) documentation.map(_ => STUB)
|
||||
else documentation) +
|
||||
s",reexport=$reexport)"
|
||||
s",reexports=$reexports)"
|
||||
}
|
||||
|
||||
/** A conversion function.
|
||||
@ -458,7 +459,7 @@ object Suggestion {
|
||||
* @param selfType the source type of a conversion
|
||||
* @param returnType the return type of a conversion
|
||||
* @param documentation the documentation string
|
||||
* @param reexport the module re-exporting this conversion
|
||||
* @param reexports modules re-exporting this conversion
|
||||
*/
|
||||
case class Conversion(
|
||||
externalId: Option[ExternalID],
|
||||
@ -467,7 +468,7 @@ object Suggestion {
|
||||
selfType: String,
|
||||
returnType: String,
|
||||
documentation: Option[String],
|
||||
reexport: Option[String] = None
|
||||
reexports: Set[String] = ListSet()
|
||||
) extends Method {
|
||||
|
||||
/** @inheritdoc */
|
||||
@ -478,15 +479,15 @@ object Suggestion {
|
||||
@JsonIgnore
|
||||
override def annotations: Seq[String] = Seq()
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexport(reexport: Option[String]): Conversion =
|
||||
copy(reexport = reexport)
|
||||
|
||||
/** @inheritdoc */
|
||||
@JsonIgnore
|
||||
override def name: String =
|
||||
Kind.Conversion.From
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexports(reexports: Set[String]): Suggestion =
|
||||
copy(reexports = reexports)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def toLogString(shouldMask: Boolean): String =
|
||||
"Conversion(" +
|
||||
@ -496,7 +497,7 @@ object Suggestion {
|
||||
s"returnType=$returnType," +
|
||||
s"documentation=" + (if (shouldMask) documentation.map(_ => STUB)
|
||||
else documentation) +
|
||||
s",reexport=$reexport)"
|
||||
s",reexports=$reexports)"
|
||||
}
|
||||
|
||||
/** A local function definition.
|
||||
@ -521,7 +522,7 @@ object Suggestion {
|
||||
with ToLogString {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexport(reexport: Option[String]): Function =
|
||||
override def withReexports(reexports: Set[String]): Suggestion =
|
||||
this
|
||||
|
||||
/** @inheritdoc */
|
||||
@ -556,7 +557,7 @@ object Suggestion {
|
||||
) extends Suggestion {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def withReexport(reexport: Option[String]): Local =
|
||||
override def withReexports(reexports: Set[String]): Suggestion =
|
||||
this
|
||||
|
||||
/** @inheritdoc */
|
||||
|
@ -1,12 +1,14 @@
|
||||
package org.enso.compiler.context;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import org.enso.pkg.QualifiedName;
|
||||
import org.enso.polyglot.ExportedSymbol;
|
||||
import org.enso.polyglot.ModuleExports;
|
||||
import org.enso.polyglot.Suggestion;
|
||||
import scala.Option;
|
||||
import scala.runtime.BoxedUnit;
|
||||
|
||||
public final class ExportsMap {
|
||||
@ -14,18 +16,27 @@ public final class ExportsMap {
|
||||
private static final String MODULE_MAIN = "Main";
|
||||
private static final String TYPE_SUFFIX = "type";
|
||||
|
||||
private final Map<ExportedSymbol, QualifiedName> exportsMap;
|
||||
private static final Comparator<QualifiedName> EXPORTS_COMPARATOR =
|
||||
Comparator.comparingInt(ExportsMap::length);
|
||||
|
||||
private final Map<ExportedSymbol, SortedSet<QualifiedName>> exportsMap;
|
||||
|
||||
public ExportsMap() {
|
||||
this.exportsMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public ExportsMap(Map<ExportedSymbol, QualifiedName> exportsMap) {
|
||||
public ExportsMap(Map<ExportedSymbol, SortedSet<QualifiedName>> exportsMap) {
|
||||
this.exportsMap = exportsMap;
|
||||
}
|
||||
|
||||
public void add(ExportedSymbol symbol, QualifiedName moduleName) {
|
||||
exportsMap.merge(symbol, moduleName, ExportsMap::getShortest);
|
||||
exportsMap.compute(
|
||||
symbol,
|
||||
(k, v) -> {
|
||||
var set = v == null ? new TreeSet<>(EXPORTS_COMPARATOR) : v;
|
||||
set.add(moduleName);
|
||||
return set;
|
||||
});
|
||||
}
|
||||
|
||||
public void addAll(QualifiedName moduleName, ModuleExports moduleExports) {
|
||||
@ -38,13 +49,10 @@ public final class ExportsMap {
|
||||
});
|
||||
}
|
||||
|
||||
public Option<QualifiedName> get(Suggestion suggestion) {
|
||||
public SortedSet<QualifiedName> get(Suggestion suggestion) {
|
||||
return ExportedSymbol.fromSuggestion(suggestion)
|
||||
.flatMap(symbol -> Option.apply(exportsMap.get(symbol)));
|
||||
}
|
||||
|
||||
private static QualifiedName getShortest(QualifiedName name1, QualifiedName name2) {
|
||||
return length(name1) <= length(name2) ? name1 : name2;
|
||||
.map(symbol -> exportsMap.getOrDefault(symbol, new TreeSet<>(EXPORTS_COMPARATOR)))
|
||||
.getOrElse(() -> new TreeSet<>(EXPORTS_COMPARATOR));
|
||||
}
|
||||
|
||||
private static int length(QualifiedName qualifiedName) {
|
||||
|
@ -16,7 +16,6 @@ final class ExportsBuilder {
|
||||
*/
|
||||
def build(moduleName: QualifiedName, ir: IR): ModuleExports = {
|
||||
val symbols = getBindings(ir).exportedSymbols.values.flatten
|
||||
.filter(_.module.getName != moduleName)
|
||||
.collect {
|
||||
case BindingsMap.ResolvedMethod(module, method) =>
|
||||
ExportedSymbol.Method(module.getName.toString, method.name)
|
||||
|
@ -13,6 +13,7 @@ import org.enso.editions.LibraryName;
|
||||
import org.enso.interpreter.runtime.EnsoContext;
|
||||
import org.enso.interpreter.runtime.util.TruffleFileSystem;
|
||||
import org.enso.interpreter.test.InterpreterContext;
|
||||
import org.enso.interpreter.util.ScalaConversions;
|
||||
import org.enso.pkg.Package;
|
||||
import org.enso.pkg.PackageManager;
|
||||
import org.enso.polyglot.LanguageInfo;
|
||||
@ -112,7 +113,9 @@ public class SerializationManagerTest {
|
||||
.filter(constructor -> constructor.name().equals("True"))
|
||||
.findFirst()
|
||||
.get();
|
||||
Assert.assertEquals(scala.Some.apply("Standard.Base.Main"), booleanTrueSuggestion.reexport());
|
||||
Assert.assertEquals(
|
||||
ScalaConversions.set("Standard.Base.Main", "Standard.Base.Data.Boolean").toList(),
|
||||
booleanTrueSuggestion.reexports().toList());
|
||||
|
||||
Suggestion.Constructor runtimeContextInputSuggestion =
|
||||
cachedConstructorSuggestions
|
||||
@ -120,7 +123,8 @@ public class SerializationManagerTest {
|
||||
.filter(constructor -> constructor.name().equals("Input"))
|
||||
.findFirst()
|
||||
.get();
|
||||
Assert.assertEquals(scala.None$.MODULE$, runtimeContextInputSuggestion.reexport());
|
||||
Assert.assertEquals(
|
||||
ScalaConversions.set().toList(), runtimeContextInputSuggestion.reexports().toList());
|
||||
|
||||
clearLibraryCache(standardBaseLibrary);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.module.scala.DefaultScalaModule;
|
||||
import java.util.List;
|
||||
import org.enso.interpreter.util.ScalaConversions;
|
||||
import org.enso.polyglot.Suggestion;
|
||||
import org.junit.Test;
|
||||
import scala.Option;
|
||||
@ -15,7 +16,8 @@ public class JacksonTest {
|
||||
|
||||
@Test
|
||||
public void testSerdeOfSuggestion() throws Exception {
|
||||
Object shape = new Suggestion.Module("SampleModule", Option.apply("doc"), Option.empty());
|
||||
Object shape =
|
||||
new Suggestion.Module("SampleModule", Option.apply("doc"), ScalaConversions.set());
|
||||
final ObjectMapper m = new ObjectMapper().registerModule(new DefaultScalaModule());
|
||||
String result = m.writerWithDefaultPrettyPrinter().writeValueAsString(shape);
|
||||
|
||||
@ -29,7 +31,7 @@ public class JacksonTest {
|
||||
public void testArraySerdeOfSuggestion() throws Exception {
|
||||
Object shape =
|
||||
new Suggestion[] {
|
||||
new Suggestion.Module("SampleModule", Option.apply("doc"), Option.empty())
|
||||
new Suggestion.Module("SampleModule", Option.apply("doc"), ScalaConversions.set())
|
||||
};
|
||||
final ObjectMapper m = new ObjectMapper().registerModule(new DefaultScalaModule());
|
||||
String result = m.writerWithDefaultPrettyPrinter().writeValueAsString(shape);
|
||||
@ -50,7 +52,9 @@ public class JacksonTest {
|
||||
Object shape =
|
||||
new SuggestionCache(
|
||||
11,
|
||||
List.of(new Suggestion.Module("SampleModule", Option.apply("doc"), Option.empty())));
|
||||
List.of(
|
||||
new Suggestion.Module(
|
||||
"SampleModule", Option.apply("doc"), ScalaConversions.set())));
|
||||
final ObjectMapper m = new ObjectMapper().registerModule(new DefaultScalaModule());
|
||||
String result = m.writerWithDefaultPrettyPrinter().writeValueAsString(shape);
|
||||
|
||||
|
@ -16,6 +16,8 @@ import java.nio.file.{Files, Paths}
|
||||
import java.util.UUID
|
||||
import java.util.logging.Level
|
||||
|
||||
import scala.collection.immutable.ListSet
|
||||
|
||||
@scala.annotation.nowarn("msg=multiarg infix syntax")
|
||||
class RuntimeSuggestionUpdatesTest
|
||||
extends AnyFlatSpec
|
||||
@ -148,7 +150,15 @@ class RuntimeSuggestionUpdatesTest
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = moduleName,
|
||||
actions = Vector(Api.SuggestionsDatabaseAction.Clean(moduleName)),
|
||||
exports = Vector(),
|
||||
exports = Vector(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
moduleName,
|
||||
ListSet(ExportedSymbol.Method(moduleName, "main"))
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
)
|
||||
),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
@ -472,7 +482,15 @@ class RuntimeSuggestionUpdatesTest
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = moduleName,
|
||||
actions = Vector(),
|
||||
exports = Vector(),
|
||||
exports = Vector(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
moduleName,
|
||||
ListSet(ExportedSymbol.Method(moduleName, "foo"))
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
)
|
||||
),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
@ -687,7 +705,15 @@ class RuntimeSuggestionUpdatesTest
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = moduleName,
|
||||
actions = Vector(Api.SuggestionsDatabaseAction.Clean(moduleName)),
|
||||
exports = Vector(),
|
||||
exports = Vector(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
moduleName,
|
||||
ListSet(ExportedSymbol.Method(moduleName, "main"))
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
)
|
||||
),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
@ -745,7 +771,15 @@ class RuntimeSuggestionUpdatesTest
|
||||
module = "Enso_Test.Foo.Main",
|
||||
actions =
|
||||
Vector(Api.SuggestionsDatabaseAction.Clean("Enso_Test.Foo.Main")),
|
||||
exports = Vector(),
|
||||
exports = Vector(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
"Enso_Test.Foo.Main",
|
||||
ListSet(ExportedSymbol.Method("Enso_Test.Foo.Main", "main"))
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
)
|
||||
),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
@ -844,7 +878,15 @@ class RuntimeSuggestionUpdatesTest
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = moduleName,
|
||||
actions = Vector(Api.SuggestionsDatabaseAction.Clean(moduleName)),
|
||||
exports = Vector(),
|
||||
exports = Vector(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
moduleName,
|
||||
ListSet(ExportedSymbol.Method(moduleName, "main"))
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
)
|
||||
),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
@ -1026,7 +1068,18 @@ class RuntimeSuggestionUpdatesTest
|
||||
module = "Enso_Test.Test.A",
|
||||
actions =
|
||||
Vector(Api.SuggestionsDatabaseAction.Clean("Enso_Test.Test.A")),
|
||||
exports = Vector(),
|
||||
exports = Vector(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
"Enso_Test.Test.A",
|
||||
ListSet(
|
||||
ExportedSymbol.Type("Enso_Test.Test.A", "MyType"),
|
||||
ExportedSymbol.Method("Enso_Test.Test.A", "hello")
|
||||
)
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
)
|
||||
),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
@ -1148,9 +1201,10 @@ class RuntimeSuggestionUpdatesTest
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
"Enso_Test.Test.Main",
|
||||
Set(
|
||||
ListSet(
|
||||
ExportedSymbol.Type("Enso_Test.Test.A", "MyType"),
|
||||
ExportedSymbol.Constructor("Enso_Test.Test.A", "MkA"),
|
||||
ExportedSymbol.Method(moduleName, "main"),
|
||||
ExportedSymbol.Method("Enso_Test.Test.A", "hello")
|
||||
)
|
||||
),
|
||||
|
@ -2,7 +2,9 @@ package org.enso.interpreter.test.instrument
|
||||
|
||||
import org.enso.interpreter.runtime.`type`.ConstantsGen
|
||||
import org.enso.polyglot.{
|
||||
ExportedSymbol,
|
||||
LanguageInfo,
|
||||
ModuleExports,
|
||||
RuntimeOptions,
|
||||
RuntimeServerInfo,
|
||||
Suggestion
|
||||
@ -21,6 +23,8 @@ import java.nio.file.{Files, Paths}
|
||||
import java.util.UUID
|
||||
import java.util.logging.Level
|
||||
|
||||
import scala.collection.immutable.ListSet
|
||||
|
||||
@scala.annotation.nowarn("msg=multiarg infix syntax")
|
||||
class RuntimeTextEditsTest
|
||||
extends AnyFlatSpec
|
||||
@ -160,7 +164,15 @@ class RuntimeTextEditsTest
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = moduleName,
|
||||
actions = Vector(Api.SuggestionsDatabaseAction.Clean(moduleName)),
|
||||
exports = Vector(),
|
||||
exports = Vector(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
moduleName,
|
||||
ListSet(ExportedSymbol.Method(moduleName, "main"))
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
)
|
||||
),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
@ -180,7 +192,7 @@ class RuntimeTextEditsTest
|
||||
moduleName,
|
||||
"main",
|
||||
List(),
|
||||
"Enso_Test.Test.Main",
|
||||
moduleName,
|
||||
ConstantsGen.ANY,
|
||||
true,
|
||||
None,
|
||||
|
@ -45,6 +45,8 @@ import org.enso.polyglot.CompilationStage;
|
||||
import org.enso.polyglot.LanguageInfo;
|
||||
import org.enso.polyglot.Suggestion;
|
||||
import org.enso.polyglot.data.TypeGraph;
|
||||
import scala.collection.immutable.ListSet;
|
||||
import scala.collection.immutable.SetOps;
|
||||
|
||||
final class TruffleCompilerContext implements CompilerContext {
|
||||
|
||||
@ -557,8 +559,12 @@ final class TruffleCompilerContext implements CompilerContext {
|
||||
})
|
||||
.map(
|
||||
suggestion -> {
|
||||
var reexport = exportsMap.get(suggestion).map(s -> s.toString());
|
||||
return suggestion.withReexport(reexport);
|
||||
scala.collection.immutable.Set<String> identity = new ListSet<>();
|
||||
var reexports =
|
||||
exportsMap.get(suggestion).stream()
|
||||
.map(QualifiedName::toString)
|
||||
.reduce(identity, SetOps::incl, SetOps::union);
|
||||
return suggestion.withReexports(reexports);
|
||||
})
|
||||
.foreach(suggestions::add);
|
||||
|
||||
@ -569,7 +575,7 @@ final class TruffleCompilerContext implements CompilerContext {
|
||||
context
|
||||
.getPackageRepository()
|
||||
.getPackageForLibraryJava(libraryName)
|
||||
.map(p -> p.listSourcesJava()));
|
||||
.map(Package::listSourcesJava));
|
||||
var cache = SuggestionsCache.create(libraryName);
|
||||
var file = saveCache(cache, cachedSuggestions, useGlobalCacheLocations);
|
||||
return file != null;
|
||||
|
@ -9,6 +9,9 @@ import scala.jdk.javaapi.OptionConverters;
|
||||
|
||||
/** Utility class for converting between Scala and Java basic classes. */
|
||||
public class ScalaConversions {
|
||||
|
||||
private ScalaConversions() {}
|
||||
|
||||
/**
|
||||
* Converts a Scala {@link Option} to a Java {@link Optional}.
|
||||
*
|
||||
@ -38,4 +41,18 @@ public class ScalaConversions {
|
||||
T head, scala.collection.immutable.List<T> tail) {
|
||||
return scala.collection.immutable.$colon$colon$.MODULE$.apply(head, tail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Scala set from the provided elements.
|
||||
*
|
||||
* @param elems the set elements.
|
||||
* @return the immutable Scala set.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <T> scala.collection.immutable.Set<T> set(T... elems) {
|
||||
var s = new scala.collection.mutable.LinkedHashSet<T>();
|
||||
for (T elem : elems) s.add(elem);
|
||||
|
||||
return s.toSet();
|
||||
}
|
||||
}
|
||||
|
@ -83,13 +83,13 @@ trait SuggestionsRepo[F[_]] {
|
||||
actions: Seq[SuggestionsDatabaseAction]
|
||||
): F[Seq[QueryResult[SuggestionsDatabaseAction]]]
|
||||
|
||||
/** Apply the sequence of export updates on the database.
|
||||
/** Get the suggestions related to the export updates.
|
||||
*
|
||||
* @param updates the list of export updates
|
||||
* @return the result of applying the updates
|
||||
* @param actions the list of updates
|
||||
* @return the suggestions ids associated with the export updates
|
||||
*/
|
||||
def applyExports(
|
||||
updates: Seq[ExportsUpdate]
|
||||
def getExportedSymbols(
|
||||
actions: Seq[ExportsUpdate]
|
||||
): F[Seq[QueryResult[ExportsUpdate]]]
|
||||
|
||||
/** Remove the suggestion.
|
||||
@ -119,8 +119,7 @@ trait SuggestionsRepo[F[_]] {
|
||||
externalId: Option[Option[Suggestion.ExternalID]],
|
||||
returnType: Option[String],
|
||||
documentation: Option[Option[String]],
|
||||
scope: Option[Suggestion.Scope],
|
||||
reexport: Option[Option[String]]
|
||||
scope: Option[Suggestion.Scope]
|
||||
): F[(Long, Option[Long])]
|
||||
|
||||
/** Update a list of suggestions by external id.
|
||||
|
@ -1,7 +1,7 @@
|
||||
package org.enso.searcher.sql
|
||||
|
||||
import org.enso.polyglot.runtime.Runtime.Api._
|
||||
import org.enso.polyglot.{ExportedSymbol, Suggestion}
|
||||
import org.enso.polyglot.Suggestion
|
||||
import org.enso.searcher.data.QueryResult
|
||||
import org.enso.searcher.{SuggestionEntry, SuggestionsRepo}
|
||||
import slick.jdbc.SQLiteProfile.api._
|
||||
@ -70,10 +70,10 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
db.run(applyActionsQuery(actions).transactionally)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def applyExports(
|
||||
updates: Seq[ExportsUpdate]
|
||||
def getExportedSymbols(
|
||||
actions: Seq[ExportsUpdate]
|
||||
): Future[Seq[QueryResult[ExportsUpdate]]] =
|
||||
db.run(applyExportsQuery(updates).transactionally)
|
||||
db.run(getExportedSymbolsQuery(actions).transactionally)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def remove(suggestion: Suggestion): Future[Option[Long]] =
|
||||
@ -89,8 +89,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
externalId: Option[Option[Suggestion.ExternalID]],
|
||||
returnType: Option[String],
|
||||
documentation: Option[Option[String]],
|
||||
scope: Option[Suggestion.Scope],
|
||||
reexport: Option[Option[String]]
|
||||
scope: Option[Suggestion.Scope]
|
||||
): Future[(Long, Option[Long])] =
|
||||
db.run(
|
||||
updateQuery(
|
||||
@ -98,8 +97,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
externalId,
|
||||
returnType,
|
||||
documentation,
|
||||
scope,
|
||||
reexport
|
||||
scope
|
||||
)
|
||||
)
|
||||
|
||||
@ -310,8 +308,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
extId,
|
||||
returnType,
|
||||
doc,
|
||||
scope,
|
||||
reexport
|
||||
scope
|
||||
)
|
||||
} else {
|
||||
DBIO.successful(None)
|
||||
@ -339,70 +336,49 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
DBIO.sequence(removeActions)
|
||||
}
|
||||
|
||||
/** The query that applies the sequence of export updates.
|
||||
/** The query to get the suggestions related to the export updates.
|
||||
*
|
||||
* @param updates the list of export updates
|
||||
* @return the result of applying actions
|
||||
* @param actions the list of updates
|
||||
* @return the suggestions ids associated with the export updates
|
||||
*/
|
||||
private def applyExportsQuery(
|
||||
updates: Seq[ExportsUpdate]
|
||||
private def getExportedSymbolsQuery(
|
||||
actions: Seq[ExportsUpdate]
|
||||
): DBIO[Seq[QueryResult[ExportsUpdate]]] = {
|
||||
def depth(module: String): Int =
|
||||
module.count(_ == '.')
|
||||
|
||||
def updateSuggestionReexport(module: String, symbol: ExportedSymbol) = {
|
||||
val moduleDepth = depth(module)
|
||||
sql"""
|
||||
update suggestions
|
||||
set reexport = $module
|
||||
where module = ${symbol.module}
|
||||
and name = ${symbol.name}
|
||||
and kind = ${SuggestionKind(symbol.kind)}
|
||||
and (
|
||||
reexport is null or
|
||||
length(reexport) - length(replace(reexport, '.', '')) > $moduleDepth
|
||||
)
|
||||
returning id
|
||||
""".as[Long]
|
||||
}
|
||||
|
||||
def unsetSuggestionReexport(module: String, symbol: ExportedSymbol) =
|
||||
sql"""
|
||||
update suggestions
|
||||
set reexport = null
|
||||
where module = ${symbol.module}
|
||||
and name = ${symbol.name}
|
||||
and kind = ${SuggestionKind(symbol.kind)}
|
||||
and reexport = $module
|
||||
returning id
|
||||
""".as[Long]
|
||||
|
||||
val actions = updates.flatMap { update =>
|
||||
val symbols = update.exports.symbols.toSeq
|
||||
update.action match {
|
||||
case ExportsAction.Add() =>
|
||||
symbols.map { symbol =>
|
||||
for {
|
||||
ids <- updateSuggestionReexport(update.exports.module, symbol)
|
||||
} yield QueryResult(ids, update)
|
||||
}
|
||||
case ExportsAction.Remove() =>
|
||||
symbols.map { symbol =>
|
||||
for {
|
||||
ids <- unsetSuggestionReexport(update.exports.module, symbol)
|
||||
} yield QueryResult(ids, update)
|
||||
}
|
||||
val qs = actions.map { action =>
|
||||
val actionIdQueries = action.exports.symbols.toSeq.map { symbol =>
|
||||
selectExportedSymbolQuery(
|
||||
symbol.module,
|
||||
symbol.name,
|
||||
symbol.kind
|
||||
).result
|
||||
}
|
||||
for {
|
||||
ids <- DBIO.sequence(actionIdQueries)
|
||||
} yield QueryResult(ids.flatten, action)
|
||||
}
|
||||
|
||||
for {
|
||||
rs <- DBIO.sequence(actions)
|
||||
_ <-
|
||||
if (rs.flatMap(_.ids).nonEmpty) incrementVersionQuery
|
||||
else DBIO.successful(())
|
||||
} yield rs
|
||||
DBIO.sequence(qs)
|
||||
}
|
||||
|
||||
/** The query to select the exported symbol.
|
||||
*
|
||||
* @param module the module name of the exported symbol
|
||||
* @param name the name of the exported symbol
|
||||
* @param kind the kind of the exported symbol
|
||||
* @return the database query returning the list of ids corresponding to the
|
||||
* exported symbol
|
||||
*/
|
||||
private def selectExportedSymbolQuery(
|
||||
module: String,
|
||||
name: String,
|
||||
kind: Suggestion.Kind
|
||||
): Query[Rep[Long], Long, Seq] =
|
||||
Suggestions
|
||||
.filter(_.module === module)
|
||||
.filter(_.kind === SuggestionKind(kind))
|
||||
.filter(_.name === name)
|
||||
.take(1)
|
||||
.map(_.id)
|
||||
|
||||
/** The query to select the suggestion.
|
||||
*
|
||||
* @param raw the suggestion converted to the row form
|
||||
@ -503,8 +479,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
externalId: Option[Option[Suggestion.ExternalID]],
|
||||
returnType: Option[String],
|
||||
documentation: Option[Option[String]],
|
||||
scope: Option[Suggestion.Scope],
|
||||
reexport: Option[Option[String]]
|
||||
scope: Option[Suggestion.Scope]
|
||||
): DBIO[(Long, Option[Long])] =
|
||||
for {
|
||||
idOpt <- updateSuggestionQuery(
|
||||
@ -512,8 +487,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
externalId,
|
||||
returnType,
|
||||
documentation,
|
||||
scope,
|
||||
reexport
|
||||
scope
|
||||
)
|
||||
version <- currentVersionQuery
|
||||
} yield (version, idOpt)
|
||||
@ -531,8 +505,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
externalId: Option[Option[Suggestion.ExternalID]],
|
||||
returnType: Option[String],
|
||||
documentation: Option[Option[String]],
|
||||
scope: Option[Suggestion.Scope],
|
||||
reexport: Option[Option[String]]
|
||||
scope: Option[Suggestion.Scope]
|
||||
): DBIO[Option[Long]] = {
|
||||
val raw = toSuggestionRow(suggestion)
|
||||
val query = selectSuggestionQuery(raw)
|
||||
@ -572,12 +545,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
)
|
||||
}
|
||||
}
|
||||
r5 <- DBIO.sequenceOption {
|
||||
reexport.map { reexportOpt =>
|
||||
query.map(_.reexport).update(reexportOpt)
|
||||
}
|
||||
}
|
||||
} yield (r1 ++ r2 ++ r3 ++ r4 ++ r5).sum
|
||||
} yield (r1 ++ r2 ++ r3 ++ r4).sum
|
||||
for {
|
||||
id <- query.map(_.id).result.headOption
|
||||
n <- updateQ
|
||||
@ -770,7 +738,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
/** Convert the suggestion to a row in the suggestions table. */
|
||||
private def toSuggestionRow(suggestion: Suggestion): SuggestionRow =
|
||||
suggestion match {
|
||||
case Suggestion.Module(module, doc, reexport) =>
|
||||
case Suggestion.Module(module, doc, _) =>
|
||||
SuggestionRow(
|
||||
id = None,
|
||||
externalIdLeast = None,
|
||||
@ -786,8 +754,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
scopeStartOffset = ScopeColumn.EMPTY,
|
||||
scopeEndLine = ScopeColumn.EMPTY,
|
||||
scopeEndOffset = ScopeColumn.EMPTY,
|
||||
documentation = doc,
|
||||
reexport = reexport
|
||||
documentation = doc
|
||||
)
|
||||
case Suggestion.Type(
|
||||
expr,
|
||||
@ -797,7 +764,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
returnType,
|
||||
parentType,
|
||||
doc,
|
||||
reexport
|
||||
_
|
||||
) =>
|
||||
SuggestionRow(
|
||||
id = None,
|
||||
@ -814,8 +781,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
scopeStartLine = ScopeColumn.EMPTY,
|
||||
scopeStartOffset = ScopeColumn.EMPTY,
|
||||
scopeEndLine = ScopeColumn.EMPTY,
|
||||
scopeEndOffset = ScopeColumn.EMPTY,
|
||||
reexport = reexport
|
||||
scopeEndOffset = ScopeColumn.EMPTY
|
||||
)
|
||||
case Suggestion.Constructor(
|
||||
expr,
|
||||
@ -825,7 +791,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
returnType,
|
||||
doc,
|
||||
_,
|
||||
reexport
|
||||
_
|
||||
) =>
|
||||
SuggestionRow(
|
||||
id = None,
|
||||
@ -842,8 +808,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
scopeStartLine = ScopeColumn.EMPTY,
|
||||
scopeStartOffset = ScopeColumn.EMPTY,
|
||||
scopeEndLine = ScopeColumn.EMPTY,
|
||||
scopeEndOffset = ScopeColumn.EMPTY,
|
||||
reexport = reexport
|
||||
scopeEndOffset = ScopeColumn.EMPTY
|
||||
)
|
||||
case Suggestion.Getter(
|
||||
expr,
|
||||
@ -854,7 +819,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
returnType,
|
||||
doc,
|
||||
_,
|
||||
reexport
|
||||
_
|
||||
) =>
|
||||
SuggestionRow(
|
||||
id = None,
|
||||
@ -871,8 +836,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
scopeStartLine = ScopeColumn.EMPTY,
|
||||
scopeStartOffset = ScopeColumn.EMPTY,
|
||||
scopeEndLine = ScopeColumn.EMPTY,
|
||||
scopeEndOffset = ScopeColumn.EMPTY,
|
||||
reexport = reexport
|
||||
scopeEndOffset = ScopeColumn.EMPTY
|
||||
)
|
||||
case Suggestion.DefinedMethod(
|
||||
expr,
|
||||
@ -884,7 +848,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
isStatic,
|
||||
doc,
|
||||
_,
|
||||
reexport
|
||||
_
|
||||
) =>
|
||||
SuggestionRow(
|
||||
id = None,
|
||||
@ -901,8 +865,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
scopeStartLine = ScopeColumn.EMPTY,
|
||||
scopeStartOffset = ScopeColumn.EMPTY,
|
||||
scopeEndLine = ScopeColumn.EMPTY,
|
||||
scopeEndOffset = ScopeColumn.EMPTY,
|
||||
reexport = reexport
|
||||
scopeEndOffset = ScopeColumn.EMPTY
|
||||
)
|
||||
case Suggestion.Conversion(
|
||||
expr,
|
||||
@ -911,7 +874,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
sourceType,
|
||||
returnType,
|
||||
doc,
|
||||
reexport
|
||||
_
|
||||
) =>
|
||||
SuggestionRow(
|
||||
id = None,
|
||||
@ -928,8 +891,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
scopeStartLine = ScopeColumn.EMPTY,
|
||||
scopeStartOffset = ScopeColumn.EMPTY,
|
||||
scopeEndLine = ScopeColumn.EMPTY,
|
||||
scopeEndOffset = ScopeColumn.EMPTY,
|
||||
reexport = reexport
|
||||
scopeEndOffset = ScopeColumn.EMPTY
|
||||
)
|
||||
case Suggestion.Function(
|
||||
expr,
|
||||
@ -955,8 +917,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
scopeStartLine = scope.start.line,
|
||||
scopeStartOffset = scope.start.character,
|
||||
scopeEndLine = scope.end.line,
|
||||
scopeEndOffset = scope.end.character,
|
||||
reexport = None
|
||||
scopeEndOffset = scope.end.character
|
||||
)
|
||||
case Suggestion.Local(expr, module, name, returnType, scope, doc) =>
|
||||
SuggestionRow(
|
||||
@ -974,8 +935,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
scopeStartLine = scope.start.line,
|
||||
scopeStartOffset = scope.start.character,
|
||||
scopeEndLine = scope.end.line,
|
||||
scopeEndOffset = scope.end.character,
|
||||
reexport = None
|
||||
scopeEndOffset = scope.end.character
|
||||
)
|
||||
}
|
||||
|
||||
@ -989,8 +949,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
case SuggestionKind.MODULE =>
|
||||
Suggestion.Module(
|
||||
module = suggestion.module,
|
||||
documentation = suggestion.documentation,
|
||||
reexport = suggestion.reexport
|
||||
documentation = suggestion.documentation
|
||||
)
|
||||
case SuggestionKind.TYPE =>
|
||||
Suggestion.Type(
|
||||
@ -1001,8 +960,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
params = Seq(),
|
||||
returnType = suggestion.returnType,
|
||||
parentType = suggestion.parentType,
|
||||
documentation = suggestion.documentation,
|
||||
reexport = suggestion.reexport
|
||||
documentation = suggestion.documentation
|
||||
)
|
||||
case SuggestionKind.CONSTRUCTOR =>
|
||||
Suggestion.Constructor(
|
||||
@ -1013,8 +971,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
arguments = Seq(),
|
||||
returnType = suggestion.returnType,
|
||||
documentation = suggestion.documentation,
|
||||
annotations = Seq(),
|
||||
reexport = suggestion.reexport
|
||||
annotations = Seq()
|
||||
)
|
||||
case SuggestionKind.GETTER =>
|
||||
Suggestion.Getter(
|
||||
@ -1026,8 +983,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
selfType = suggestion.selfType,
|
||||
returnType = suggestion.returnType,
|
||||
documentation = suggestion.documentation,
|
||||
annotations = Seq(),
|
||||
reexport = suggestion.reexport
|
||||
annotations = Seq()
|
||||
)
|
||||
case SuggestionKind.METHOD =>
|
||||
Suggestion.DefinedMethod(
|
||||
@ -1040,8 +996,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
returnType = suggestion.returnType,
|
||||
isStatic = suggestion.isStatic,
|
||||
documentation = suggestion.documentation,
|
||||
annotations = Seq(),
|
||||
reexport = suggestion.reexport
|
||||
annotations = Seq()
|
||||
)
|
||||
case SuggestionKind.CONVERSION =>
|
||||
Suggestion.Conversion(
|
||||
@ -1051,8 +1006,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
arguments = Seq(),
|
||||
selfType = suggestion.selfType,
|
||||
returnType = suggestion.returnType,
|
||||
documentation = suggestion.documentation,
|
||||
reexport = suggestion.reexport
|
||||
documentation = suggestion.documentation
|
||||
)
|
||||
case SuggestionKind.FUNCTION =>
|
||||
Suggestion.Function(
|
||||
|
@ -38,8 +38,7 @@ case class SuggestionRow(
|
||||
scopeStartOffset: Int,
|
||||
scopeEndLine: Int,
|
||||
scopeEndOffset: Int,
|
||||
documentation: Option[String],
|
||||
reexport: Option[String]
|
||||
documentation: Option[String]
|
||||
)
|
||||
|
||||
/** A row in the suggestions_version table.
|
||||
@ -143,7 +142,6 @@ final class SuggestionsTable(tag: Tag)
|
||||
def scopeEndOffset =
|
||||
column[Int]("scope_end_offset", O.Default(ScopeColumn.EMPTY))
|
||||
def documentation = column[Option[String]]("documentation")
|
||||
def reexport = column[Option[String]]("reexport")
|
||||
|
||||
def * =
|
||||
(
|
||||
@ -161,8 +159,7 @@ final class SuggestionsTable(tag: Tag)
|
||||
scopeStartOffset,
|
||||
scopeEndLine,
|
||||
scopeEndOffset,
|
||||
documentation,
|
||||
reexport
|
||||
documentation
|
||||
) <>
|
||||
(SuggestionRow.tupled, SuggestionRow.unapply)
|
||||
|
||||
@ -172,7 +169,7 @@ final class SuggestionsTable(tag: Tag)
|
||||
def returnTypeIdx = index("suggestions_return_type_idx", returnType)
|
||||
def externalIdIdx =
|
||||
index("suggestions_external_id_idx", (externalIdLeast, externalIdMost))
|
||||
def reexportIdx = index("suggestions_reexport_idx", reexport)
|
||||
|
||||
// NOTE: unique index should not contain nullable columns because SQLite
|
||||
// teats NULLs as distinct values.
|
||||
def uniqueIdx =
|
||||
@ -288,5 +285,5 @@ object SuggestionsVersion extends TableQuery(new SuggestionsVersionTable(_))
|
||||
object SchemaVersion extends TableQuery(new SchemaVersionTable(_)) {
|
||||
|
||||
/** The current schema version. */
|
||||
val CurrentVersion: Long = 11
|
||||
val CurrentVersion: Long = 12
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package org.enso.searcher.sql
|
||||
|
||||
import java.nio.file.{Files, Path}
|
||||
import java.util.UUID
|
||||
import org.enso.polyglot.{ExportedSymbol, ModuleExports, Suggestion}
|
||||
import org.enso.polyglot.runtime.Runtime.Api
|
||||
import org.enso.searcher.SuggestionEntry
|
||||
@ -13,6 +11,9 @@ import org.scalactic.TripleEqualsSupport
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
import java.nio.file.{Files, Path}
|
||||
import java.util.UUID
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import scala.concurrent.duration._
|
||||
@ -69,7 +70,7 @@ class SuggestionsRepoTest
|
||||
thrown.version shouldEqual wrongSchemaVersion
|
||||
}
|
||||
|
||||
"insert all suggestions111" taggedAs Retry in withRepo { repo =>
|
||||
"insert all suggestions" taggedAs Retry in withRepo { repo =>
|
||||
val action =
|
||||
for {
|
||||
v1 <- repo.currentVersion
|
||||
@ -284,7 +285,6 @@ class SuggestionsRepoTest
|
||||
Some(Some(newUuid)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -314,7 +314,6 @@ class SuggestionsRepoTest
|
||||
Some(None),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -344,7 +343,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
Some(newReturnType),
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -374,7 +372,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
Some(Some(newDoc)),
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -407,7 +404,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
Some(Some(newDoc)),
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -440,7 +436,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
Some(Some(newDoc)),
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -471,7 +466,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
Some(Some(newDoc)),
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -504,7 +498,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
Some(Some(newDoc)),
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -536,7 +529,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
Some(Some(newDoc)),
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -568,7 +560,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
Some(None),
|
||||
None,
|
||||
None
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
@ -601,8 +592,7 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(newScope),
|
||||
None
|
||||
Some(newScope)
|
||||
)
|
||||
s <- repo.select(id1)
|
||||
} yield (v1, id1, v2, id2, s)
|
||||
@ -630,7 +620,6 @@ class SuggestionsRepoTest
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
} yield (v1, v2, id1, id2)
|
||||
@ -679,9 +668,9 @@ class SuggestionsRepoTest
|
||||
v1 shouldEqual v2
|
||||
}
|
||||
|
||||
"apply export updates" taggedAs Retry in withRepo { repo =>
|
||||
"get exported symbols" taggedAs Retry in withRepo { repo =>
|
||||
val reexport = "Foo.Bar"
|
||||
val method = suggestion.method.copy(reexport = Some(reexport))
|
||||
val method = suggestion.method.copy(reexports = Set(reexport))
|
||||
val updates = Seq(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
@ -710,7 +699,7 @@ class SuggestionsRepoTest
|
||||
suggestion.local
|
||||
)
|
||||
)
|
||||
results <- repo.applyExports(updates)
|
||||
results <- repo.getExportedSymbols(updates)
|
||||
} yield (ids, results)
|
||||
|
||||
val (ids, results) = Await.result(action, Timeout)
|
||||
@ -720,126 +709,6 @@ class SuggestionsRepoTest
|
||||
)
|
||||
}
|
||||
|
||||
"not apply exports with bigger module name" taggedAs Retry in withRepo {
|
||||
repo =>
|
||||
val reexport = "Foo.Bar.Baz"
|
||||
val method = suggestion.method.copy(reexport = Some("Foo.Bar"))
|
||||
val updates = Seq(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
reexport,
|
||||
Set(ExportedSymbol.Module(suggestion.module.module))
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
),
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
reexport,
|
||||
Set(ExportedSymbol.Method(method.module, method.name))
|
||||
),
|
||||
Api.ExportsAction.Remove()
|
||||
)
|
||||
)
|
||||
val action = for {
|
||||
(_, ids) <- repo.insertAll(
|
||||
Seq(
|
||||
suggestion.module,
|
||||
suggestion.tpe,
|
||||
suggestion.constructor,
|
||||
method,
|
||||
suggestion.conversion,
|
||||
suggestion.function,
|
||||
suggestion.local
|
||||
)
|
||||
)
|
||||
results <- repo.applyExports(updates)
|
||||
} yield (ids, results)
|
||||
|
||||
val (ids, results) = Await.result(action, Timeout)
|
||||
results should contain theSameElementsAs Seq(
|
||||
QueryResult(Seq(ids(0)), updates(0)),
|
||||
QueryResult(Seq(), updates(1))
|
||||
)
|
||||
}
|
||||
|
||||
"change version after applying exports" taggedAs Retry in withRepo { repo =>
|
||||
val reexport = "Foo.Bar"
|
||||
val method = suggestion.method.copy(reexport = Some(reexport))
|
||||
val updates = Seq(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
reexport,
|
||||
Set(ExportedSymbol.Module(suggestion.module.module))
|
||||
),
|
||||
Api.ExportsAction.Add()
|
||||
),
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
reexport,
|
||||
Set(ExportedSymbol.Method(method.module, method.name))
|
||||
),
|
||||
Api.ExportsAction.Remove()
|
||||
)
|
||||
)
|
||||
val action = for {
|
||||
_ <- repo.insertAll(
|
||||
Seq(
|
||||
suggestion.module,
|
||||
suggestion.tpe,
|
||||
suggestion.constructor,
|
||||
method,
|
||||
suggestion.conversion,
|
||||
suggestion.function,
|
||||
suggestion.local
|
||||
)
|
||||
)
|
||||
v1 <- repo.currentVersion
|
||||
results <- repo.applyExports(updates)
|
||||
v2 <- repo.currentVersion
|
||||
} yield (results, v1, v2)
|
||||
|
||||
val (results, v1, v2) = Await.result(action, Timeout)
|
||||
results.flatMap(_.ids).isEmpty shouldBe false
|
||||
v1 should not equal v2
|
||||
}
|
||||
|
||||
"not change version when exports not applied" taggedAs Retry in withRepo {
|
||||
repo =>
|
||||
val reexport = "Foo.Bar"
|
||||
val updates = Seq(
|
||||
Api.ExportsUpdate(
|
||||
ModuleExports(
|
||||
reexport,
|
||||
Set(
|
||||
ExportedSymbol
|
||||
.Method(suggestion.method.module, suggestion.method.name)
|
||||
)
|
||||
),
|
||||
Api.ExportsAction.Remove()
|
||||
)
|
||||
)
|
||||
val action = for {
|
||||
_ <- repo.insertAll(
|
||||
Seq(
|
||||
suggestion.module,
|
||||
suggestion.tpe,
|
||||
suggestion.constructor,
|
||||
suggestion.method,
|
||||
suggestion.conversion,
|
||||
suggestion.function,
|
||||
suggestion.local
|
||||
)
|
||||
)
|
||||
v1 <- repo.currentVersion
|
||||
results <- repo.applyExports(updates)
|
||||
v2 <- repo.currentVersion
|
||||
} yield (results, v1, v2)
|
||||
|
||||
val (results, v1, v2) = Await.result(action, Timeout)
|
||||
results.flatMap(_.ids).isEmpty shouldBe true
|
||||
v1 shouldEqual v2
|
||||
}
|
||||
|
||||
"search suggestion by empty query" taggedAs Retry in withRepo { repo =>
|
||||
val action = for {
|
||||
_ <- repo.insert(suggestion.module)
|
||||
|
Loading…
Reference in New Issue
Block a user