From a1f2560491599def3bfa3721d7ab3757b2ea4c15 Mon Sep 17 00:00:00 2001 From: Dmitry Bushev Date: Wed, 6 Sep 2023 12:02:21 +0100 Subject: [PATCH] Fix re-exports of type constructors (#7724) close #7674 Changelog: - fix: setting reexport field when serializing the library --- .../org/enso/compiler/context/ExportsMap.java | 9 +- .../enso/compiler/SerializationManager.scala | 6 +- .../compiler/SerializationManagerTest.java | 127 ++++++++++++++++++ .../org/enso/compiler/test/CompilerTest.scala | 2 +- .../interpreter/test/InterpreterTest.scala | 16 +-- 5 files changed, 140 insertions(+), 20 deletions(-) create mode 100644 engine/runtime/src/test/java/org/enso/compiler/SerializationManagerTest.java diff --git a/engine/runtime/src/main/java/org/enso/compiler/context/ExportsMap.java b/engine/runtime/src/main/java/org/enso/compiler/context/ExportsMap.java index 1b5e9dfbd8e..70f203a9c48 100644 --- a/engine/runtime/src/main/java/org/enso/compiler/context/ExportsMap.java +++ b/engine/runtime/src/main/java/org/enso/compiler/context/ExportsMap.java @@ -38,14 +38,9 @@ public final class ExportsMap { }); } - public QualifiedName get(ExportedSymbol symbol) { - return exportsMap.get(symbol); - } - - public QualifiedName get(Suggestion suggestion) { + public Option get(Suggestion suggestion) { return ExportedSymbol.fromSuggestion(suggestion) - .flatMap(symbol -> Option.apply(exportsMap.get(symbol))) - .getOrElse(() -> exportsMap.get(ExportedSymbol.suggestionModule(suggestion))); + .flatMap(symbol -> Option.apply(exportsMap.get(symbol))); } private static QualifiedName getShortest(QualifiedName name1, QualifiedName name2) { 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 5977965330e..78e53dee603 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala @@ -26,9 +26,7 @@ import java.util.logging.Level import scala.collection.mutable import scala.jdk.OptionConverters.RichOptional -final class SerializationManager( - compiler: Compiler -) { +final class SerializationManager(compiler: Compiler) { import SerializationManager._ @@ -260,7 +258,7 @@ final class SerializationManager( suggestions } .map { suggestion => - val reexport = Option(exportsMap.get(suggestion)).map(_.toString) + val reexport = exportsMap.get(suggestion).map(_.toString) suggestion.withReexport(reexport) } .foreach(suggestions.add) diff --git a/engine/runtime/src/test/java/org/enso/compiler/SerializationManagerTest.java b/engine/runtime/src/test/java/org/enso/compiler/SerializationManagerTest.java new file mode 100644 index 00000000000..b776b592edc --- /dev/null +++ b/engine/runtime/src/test/java/org/enso/compiler/SerializationManagerTest.java @@ -0,0 +1,127 @@ +package org.enso.compiler; + +import com.oracle.truffle.api.TruffleFile; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; +import java.util.stream.Stream; +import org.apache.commons.io.FileUtils; +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.pkg.Package; +import org.enso.pkg.PackageManager; +import org.enso.polyglot.LanguageInfo; +import org.enso.polyglot.MethodNames; +import org.enso.polyglot.Suggestion; +import org.junit.*; + +public class SerializationManagerTest { + + private static final long COMPILE_TIMEOUT_SECONDS = 20; + + private final PackageManager packageManager; + private final InterpreterContext interpreterContext; + private final EnsoContext ensoContext; + + public SerializationManagerTest() { + packageManager = new PackageManager<>(new TruffleFileSystem()); + interpreterContext = new InterpreterContext(x -> x); + ensoContext = + interpreterContext + .ctx() + .getBindings(LanguageInfo.ID) + .invokeMember(MethodNames.TopScope.LEAK_CONTEXT) + .asHostObject(); + } + + @Before + public void setup() { + interpreterContext.ctx().initialize(LanguageInfo.ID); + interpreterContext.ctx().enter(); + } + + @After + public void teardown() { + interpreterContext.ctx().close(); + } + + private Path getLibraryPath(LibraryName libraryName) { + return Paths.get( + interpreterContext.languageHome(), + "..", + "lib", + libraryName.namespace(), + libraryName.name(), + interpreterContext.edition()) + .toAbsolutePath() + .normalize(); + } + + private Package getLibraryPackage(LibraryName libraryName) { + Path libraryPath = getLibraryPath(libraryName); + TruffleFile libraryFile = + ensoContext.getEnvironment().getInternalTruffleFile(libraryPath.toString()); + return packageManager.loadPackage(libraryFile).get(); + } + + private void clearLibraryCache(LibraryName libraryName) { + Path libraryCachePath = Paths.get(getLibraryPath(libraryName).toString(), ".enso"); + FileUtils.deleteQuietly(libraryCachePath.toFile()); + } + + @Test + public void serializeLibrarySuggestions() + throws ExecutionException, InterruptedException, TimeoutException { + SerializationManager serializationManager = new SerializationManager(ensoContext.getCompiler()); + LibraryName standardBaseLibrary = new LibraryName("Standard", "Base"); + Package standardBasePackage = getLibraryPackage(standardBaseLibrary); + ensoContext + .getPackageRepository() + .registerMainProjectPackage(standardBaseLibrary, standardBasePackage); + + Object result = + ensoContext + .getCompiler() + .compile(false, false) + .get(COMPILE_TIMEOUT_SECONDS, TimeUnit.SECONDS); + Assert.assertEquals(Boolean.TRUE, result); + + SuggestionsCache.CachedSuggestions cachedSuggestions = + serializationManager.deserializeSuggestions(standardBaseLibrary).get(); + Assert.assertEquals(standardBaseLibrary, cachedSuggestions.getLibraryName()); + + Supplier> cachedConstructorSuggestions = + () -> + cachedSuggestions.getSuggestions().stream() + .flatMap( + suggestion -> { + if (suggestion instanceof Suggestion.Constructor constructor) { + return Stream.of(constructor); + } + return Stream.empty(); + }); + + Suggestion.Constructor booleanTrueSuggestion = + cachedConstructorSuggestions + .get() + .filter(constructor -> constructor.name().equals("True")) + .findFirst() + .get(); + Assert.assertEquals(scala.Some.apply("Standard.Base.Main"), booleanTrueSuggestion.reexport()); + + Suggestion.Constructor runtimeContextInputSuggestion = + cachedConstructorSuggestions + .get() + .filter(constructor -> constructor.name().equals("Input")) + .findFirst() + .get(); + Assert.assertEquals(scala.None$.MODULE$, runtimeContextInputSuggestion.reexport()); + + clearLibraryCache(standardBaseLibrary); + } +} diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/CompilerTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/CompilerTest.scala index c4fd6abf4e2..0de1f2a7c75 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/CompilerTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/CompilerTest.scala @@ -205,7 +205,7 @@ trait CompilerRunner { passConfiguration: Option[PassConfiguration] = None, compilerConfig: CompilerConfig = defaultConfig, isGeneratingDocs: Boolean = false - ) = buildModuleContextModule( + ): ModuleContext = buildModuleContextModule( moduleName, freshNameSupply, passConfiguration, diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/InterpreterTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/InterpreterTest.scala index 9a3b8c89674..d24c8558346 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/InterpreterTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/InterpreterTest.scala @@ -108,6 +108,12 @@ class InterpreterContext( val in = new PipedInputStream(inOut) val sessionManager = new ReplaceableSessionManager + val languageHome = Paths + .get("../../test/micro-distribution/component") + .toFile + .getAbsolutePath + val edition = "0.0.0-dev" + val ctx = contextModifiers( Context .newBuilder(LanguageInfo.ID) @@ -121,14 +127,8 @@ class InterpreterContext( .environment("NO_COLOR", "true") .logHandler(System.err) .in(in) - .option( - RuntimeOptions.LANGUAGE_HOME_OVERRIDE, - Paths - .get("../../test/micro-distribution/component") - .toFile - .getAbsolutePath - ) - .option(RuntimeOptions.EDITION_OVERRIDE, "0.0.0-dev") + .option(RuntimeOptions.LANGUAGE_HOME_OVERRIDE, languageHome) + .option(RuntimeOptions.EDITION_OVERRIDE, edition) .serverTransport { (uri, peer) => if (uri.toString == DebugServerInfo.URI) { new DebuggerSessionManagerEndpoint(sessionManager, peer)