diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/libraries/EditionReferenceResolver.scala b/engine/language-server/src/main/scala/org/enso/languageserver/libraries/EditionReferenceResolver.scala index aeb694a748..7edef3432c 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/libraries/EditionReferenceResolver.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/libraries/EditionReferenceResolver.scala @@ -31,7 +31,7 @@ class EditionReferenceResolver( } /** Returns the configuration of the current project. */ - def getCurrentProjectConfig: Try[Config] = Try { projectPackage.config } + def getCurrentProjectConfig: Try[Config] = Try { projectPackage.getConfig() } /** Resolves all edition dependencies of an edition identified by * [[EditionReference]]. diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/libraries/LocalLibraryManager.scala b/engine/language-server/src/main/scala/org/enso/languageserver/libraries/LocalLibraryManager.scala index 729929b77d..061e8cec29 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/libraries/LocalLibraryManager.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/libraries/LocalLibraryManager.scala @@ -245,7 +245,7 @@ class LocalLibraryManager( */ private def findCurrentProjectEdition(): Option[Editions.RawEdition] = { val pkg = PackageManager.Default.loadPackage(currentProjectRoot).get - pkg.config.edition + pkg.getConfig().edition } } diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/libraries/ProjectSettingsManager.scala b/engine/language-server/src/main/scala/org/enso/languageserver/libraries/ProjectSettingsManager.scala index af2ea91d0e..cf6e1c45fd 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/libraries/ProjectSettingsManager.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/libraries/ProjectSettingsManager.scala @@ -27,13 +27,16 @@ class ProjectSettingsManager( private def loadSettings(): Try[SettingsResponse] = for { pkg <- PackageManager.Default.loadPackage(projectRoot) - edition = pkg.config.edition.getOrElse(DefaultEdition.getDefaultEdition) - } yield SettingsResponse(edition.parent, pkg.config.preferLocalLibraries) + edition = pkg + .getConfig() + .edition + .getOrElse(DefaultEdition.getDefaultEdition) + } yield SettingsResponse(edition.parent, pkg.getConfig().preferLocalLibraries) private def setParentEdition(editionName: String): Try[SettingsUpdated] = for { pkg <- PackageManager.Default.loadPackage(projectRoot) - newEdition = pkg.config.edition match { + newEdition = pkg.getConfig().edition match { case Some(edition) => edition.copy(parent = Some(editionName)) case None => Editions.Raw.Edition(parent = Some(editionName)) } diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/requesthandler/workspace/ProjectInfoHandler.scala b/engine/language-server/src/main/scala/org/enso/languageserver/requesthandler/workspace/ProjectInfoHandler.scala index 1a7cd5a3ef..1ea2748de9 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/requesthandler/workspace/ProjectInfoHandler.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/requesthandler/workspace/ProjectInfoHandler.scala @@ -10,8 +10,8 @@ import org.enso.languageserver.util.UnhandledLogging import org.enso.languageserver.workspace.WorkspaceApi.ProjectInfo import org.enso.logger.masking.MaskedPath import org.enso.pkg.{Config => PkgConfig} -import java.io.{File, FileInputStream} -import java.nio.charset.StandardCharsets + +import java.io.{File, FileReader} /** A request handler for `workspace/openFile` commands. */ @@ -26,10 +26,7 @@ class ProjectInfoHandler(languageServerConfig: Config) if (configFile.exists()) { val projectConfig = PkgConfig.fromYaml( - new String( - new FileInputStream(configFile).readAllBytes(), - StandardCharsets.UTF_8 - ) + new FileReader(configFile) ) if (projectConfig.isSuccess) { val projectInfo = ProjectInfo.Result( diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/search/SuggestionsHandler.scala b/engine/language-server/src/main/scala/org/enso/languageserver/search/SuggestionsHandler.scala index bb52963126..e9dc4ea45e 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/search/SuggestionsHandler.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/search/SuggestionsHandler.scala @@ -145,7 +145,7 @@ final class SuggestionsHandler( MaskedPath(config.projectContentRoot.file.toPath), t ), - pkg => self ! ProjectNameUpdated(pkg.config.name) + pkg => self ! ProjectNameUpdated(pkg.getConfig().name) ) val requestId = UUID.randomUUID() runtimeConnector ! Api.Request(requestId, Api.GetTypeGraphRequest()) diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/LibrariesTest.scala b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/LibrariesTest.scala index 2e8844ac66..65497d21df 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/LibrariesTest.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/LibrariesTest.scala @@ -463,10 +463,10 @@ class LibrariesTest extends BaseServerTest { val mainPackage = libraryRoot.resolve("main.tgz") assert(Files.exists(mainPackage)) val pkg = PackageManager.Default.loadPackage(libraryRoot.toFile).get - pkg.config.authors should contain theSameElementsAs Seq( + pkg.getConfig().authors should contain theSameElementsAs Seq( Contact(name = Some("user"), email = Some("example@example.com")) ) - pkg.config.maintainers should contain theSameElementsAs Seq( + pkg.getConfig().maintainers should contain theSameElementsAs Seq( Contact(name = Some("only-name"), email = None), Contact(name = None, email = Some("foo@example.com")) ) diff --git a/engine/runner/src/main/scala/org/enso/runner/DependencyPreinstaller.scala b/engine/runner/src/main/scala/org/enso/runner/DependencyPreinstaller.scala index eb1f52d4c5..b357d97260 100644 --- a/engine/runner/src/main/scala/org/enso/runner/DependencyPreinstaller.scala +++ b/engine/runner/src/main/scala/org/enso/runner/DependencyPreinstaller.scala @@ -49,7 +49,7 @@ object DependencyPreinstaller { val editionResolver = EditionResolver(editionProvider) val edition = editionResolver .resolve( - pkg.config.edition.getOrElse(DefaultEdition.getDefaultEdition) + pkg.getConfig().edition.getOrElse(DefaultEdition.getDefaultEdition) ) match { case Left(error) => throw new RuntimeException( @@ -58,7 +58,7 @@ object DependencyPreinstaller { case Right(value) => value } - val preferLocalLibraries = pkg.config.preferLocalLibraries + val preferLocalLibraries = pkg.getConfig().preferLocalLibraries val (localLibraryProvider, publishedLibraryProvider) = DefaultLibraryProvider.makeProviders( diff --git a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/command/RenameProjectCmd.scala b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/command/RenameProjectCmd.scala index e0ed642d44..fef935623f 100644 --- a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/command/RenameProjectCmd.scala +++ b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/command/RenameProjectCmd.scala @@ -43,6 +43,13 @@ class RenameProjectCmd( val projectModules = getProjectModules projectModules.foreach { module => module.setIndexed(false) + val newConfig = module.getPackage.reloadConfig() + if (newConfig.isFailure) { + logger.log( + Level.WARNING, + s"Failed to reload package's config: ${newConfig.failed.get.getMessage}" + ) + } ctx.endpoint.sendToClient( Api.Response( Api.SuggestionsDatabaseModuleUpdateNotification( diff --git a/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeComponentsTest.scala b/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeComponentsTest.scala index 1b5631a451..ab10066bd6 100644 --- a/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeComponentsTest.scala +++ b/engine/runtime-with-instruments/src/test/scala/org/enso/interpreter/test/instrument/RuntimeComponentsTest.scala @@ -271,7 +271,9 @@ class RuntimeComponentsTest // check the registered component groups val components = context.languageContext.getPackageRepository.getComponents components.get(LibraryName("Enso_Test", "Test")).value shouldEqual - context.pkg.config.componentGroups + context.pkg + .getConfig() + .componentGroups .getOrElse(fail("Unexpected config value.")) components @@ -348,7 +350,9 @@ class RuntimeComponentsTest val components = context.languageContext.getPackageRepository.getComponents components.get(LibraryName("Enso_Test", "Test")).value shouldEqual - context.pkg.config.componentGroups + context.pkg + .getConfig() + .componentGroups .getOrElse(fail("Unexpected config value.")) components diff --git a/engine/runtime/src/main/java/org/enso/compiler/ImportExportCache.java b/engine/runtime/src/main/java/org/enso/compiler/ImportExportCache.java index ff7d8760eb..18ec63f8d7 100644 --- a/engine/runtime/src/main/java/org/enso/compiler/ImportExportCache.java +++ b/engine/runtime/src/main/java/org/enso/compiler/ImportExportCache.java @@ -92,7 +92,7 @@ public final class ImportExportCache extends Cache pkg) { EnsoFile rootPath = new EnsoFile(pkg.root().normalize()); - Object cfg = ctx.getEnvironment().asGuestValue(pkg.config()); + Object cfg = ctx.getEnvironment().asGuestValue(pkg.getConfig()); return ctx.getBuiltins() .getProjectDescription() .getUniqueConstructor() diff --git a/engine/runtime/src/main/scala/org/enso/compiler/PackageRepository.scala b/engine/runtime/src/main/scala/org/enso/compiler/PackageRepository.scala index 2f7e56ff1c..bf5b7141fb 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/PackageRepository.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/PackageRepository.scala @@ -463,7 +463,7 @@ object PackageRepository { ): Either[Error, Unit] = if (loadedComponents.contains(pkg.libraryName)) Right(()) else { - pkg.config.componentGroups match { + pkg.getConfig().componentGroups match { case Left(err) => Left(Error.PackageLoadingError(err.getMessage())) case Right(componentGroups) => @@ -760,7 +760,7 @@ object PackageRepository { .map(v => Editions.Raw.Edition(parent = Some(v))) .orElse( projectPackage - .flatMap(_.config.edition) + .flatMap(_.getConfig().edition) ) .getOrElse(DefaultEdition.getDefaultEdition) @@ -777,7 +777,7 @@ object PackageRepository { languageHome = homeManager, edition = edition, preferLocalLibraries = - projectPackage.exists(_.config.preferLocalLibraries) + projectPackage.exists(_.getConfig().preferLocalLibraries) ) new Default( resolvingLibraryProvider, diff --git a/lib/scala/library-manager/src/main/scala/org/enso/librarymanager/LibraryResolver.scala b/lib/scala/library-manager/src/main/scala/org/enso/librarymanager/LibraryResolver.scala index 0ad50cce9d..dac04dc1bd 100644 --- a/lib/scala/library-manager/src/main/scala/org/enso/librarymanager/LibraryResolver.scala +++ b/lib/scala/library-manager/src/main/scala/org/enso/librarymanager/LibraryResolver.scala @@ -66,6 +66,7 @@ case class LibraryResolver( case Some(parentEdition) => resolveLibraryFromEdition(libraryName, parentEdition) case None => + new Exception("library not found").printStackTrace() Left( LibraryResolutionError( s"The library `$libraryName` is not defined within " + diff --git a/lib/scala/library-manager/src/main/scala/org/enso/libraryupload/LibraryUploader.scala b/lib/scala/library-manager/src/main/scala/org/enso/libraryupload/LibraryUploader.scala index 4e7858fe32..a59351fa8a 100644 --- a/lib/scala/library-manager/src/main/scala/org/enso/libraryupload/LibraryUploader.scala +++ b/lib/scala/library-manager/src/main/scala/org/enso/libraryupload/LibraryUploader.scala @@ -44,9 +44,9 @@ class LibraryUploader(dependencyExtractor: DependencyExtractor[File]) { )(implicit ec: ExecutionContext): Try[Unit] = Try { FileSystem.withTemporaryDirectory("enso-upload") { tmpDir => val pkg = PackageManager.Default.loadPackage(projectRoot.toFile).get - val version = SemVer(pkg.config.version).getOrElse { + val version = SemVer(pkg.getConfig().version).getOrElse { throw new IllegalStateException( - s"Project version [${pkg.config.version}] is not a valid semver " + + s"Project version [${pkg.getConfig().version}] is not a valid semver " + s"string." ) } diff --git a/lib/scala/pkg/src/main/scala/org/enso/pkg/Config.scala b/lib/scala/pkg/src/main/scala/org/enso/pkg/Config.scala index 6ac1ed2f87..240f61c200 100644 --- a/lib/scala/pkg/src/main/scala/org/enso/pkg/Config.scala +++ b/lib/scala/pkg/src/main/scala/org/enso/pkg/Config.scala @@ -13,6 +13,7 @@ import org.enso.editions.{ SemVerEnsoVersion } +import java.io.Reader import scala.util.Try /** An extra project dependency. @@ -250,6 +251,11 @@ object Config { yaml.parser.parse(yamlString).flatMap(_.as[Config]).toTry } + /** Tries to parse the [[Config]] directly from the Reader */ + def fromYaml(reader: Reader): Try[Config] = { + yaml.parser.parse(reader).flatMap(_.as[Config]).toTry + } + /** Creates a simple edition that just defines the provided engine version. * * A compatibility layer for migrating from just specifying the engine diff --git a/lib/scala/pkg/src/main/scala/org/enso/pkg/Package.scala b/lib/scala/pkg/src/main/scala/org/enso/pkg/Package.scala index cb9194a372..fb8a54f508 100644 --- a/lib/scala/pkg/src/main/scala/org/enso/pkg/Package.scala +++ b/lib/scala/pkg/src/main/scala/org/enso/pkg/Package.scala @@ -25,9 +25,9 @@ case class SourceFile[F](qualifiedName: QualifiedName, file: F) * @param config the metadata contained in the package configuration * @param fileSystem the file system access module */ -case class Package[F]( - root: F, - config: Config, +class Package[F]( + val root: F, + initialConfig: Config, implicit val fileSystem: FileSystem[F] ) { import FileSystem.Syntax @@ -47,13 +47,25 @@ case class Package[F]( .getChild(Package.cacheDirName) .getChild(Package.suggestionsCacheDirName) + private[this] var config: Config = initialConfig + def getConfig(): Config = config + + /** Reloads the config from file system */ + def reloadConfig(): Try[Config] = { + val configFile = root.getChild(Package.configFileName) + val newConfig = Using(configFile.newBufferedReader)(Config.fromYaml).flatten + newConfig.foreach(config = _) + newConfig + } + /** Sets the package name. * * @param newName the new package name * @return a package with the updated name */ - def setPackageName(newName: String): Package[F] = - this.copy(config = config.copy(name = newName)) + def setPackageName(newName: String): Package[F] = { + new Package(root, config.copy(name = newName), fileSystem) + } /** Stores the package metadata on the hard drive. If the package does not exist, * creates the required directory structure. @@ -126,7 +138,7 @@ case class Package[F]( * valid anymore. */ def updateConfig(update: Config => Config): Package[F] = { - val newPkg = copy(config = update(config)) + val newPkg = new Package(root, update(config), fileSystem) newPkg.saveConfig() newPkg } @@ -234,7 +246,7 @@ class PackageManager[F](implicit val fileSystem: FileSystem[F]) { config: Config, template: Template ): Package[F] = { - val pkg = Package(root, config, fileSystem) + val pkg = new Package(root, config, fileSystem) pkg.save() copyResources(pkg, template) pkg @@ -300,18 +312,15 @@ class PackageManager[F](implicit val fileSystem: FileSystem[F]) { val result = if (!root.exists) Failure(PackageManager.PackageNotFound()) else { - def readConfig(file: F): Try[String] = + def readConfig(file: F): Try[Config] = if (file.exists) - Using(file.newBufferedReader) { reader => - reader.lines().iterator().asScala.mkString("\n") - } + Using(file.newBufferedReader)(Config.fromYaml).flatten else Failure(PackageManager.PackageNotFound()) val configFile = root.getChild(Package.configFileName) for { - resultStr <- readConfig(configFile) - result <- Config.fromYaml(resultStr) - } yield Package(root, result, fileSystem) + result <- readConfig(configFile) + } yield new Package(root, result, fileSystem) } result.recoverWith { case packageLoadingException: PackageManager.PackageLoadingException => diff --git a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/repository/ProjectFileRepository.scala b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/repository/ProjectFileRepository.scala index 76b6626dc9..24eff8e4b8 100644 --- a/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/repository/ProjectFileRepository.scala +++ b/lib/scala/project-manager/src/main/scala/org/enso/projectmanager/infrastructure/repository/ProjectFileRepository.scala @@ -109,7 +109,7 @@ class ProjectFileRepository[ namespace = pkg.namespace, kind = meta.kind, created = meta.created, - edition = pkg.config.edition, + edition = pkg.getConfig().edition, lastOpened = meta.lastOpened, path = Some(directory.toString), directoryCreationTime = directoryCreationTime @@ -156,7 +156,7 @@ class ProjectFileRepository[ for { project <- getProject(projectId) projectPackage <- getPackage(new File(project.path.get)) - } yield projectPackage.config.name + } yield projectPackage.getConfig().name } /** @inheritdoc */ @@ -166,7 +166,7 @@ class ProjectFileRepository[ for { project <- getProject(projectId) projectPackage <- getPackage(new File(project.path.get)) - } yield projectPackage.config.namespace + } yield projectPackage.getConfig().namespace } private def loadPackage( diff --git a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/runner/Project.scala b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/runner/Project.scala index fbdb689f91..a4ecab61a8 100644 --- a/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/runner/Project.scala +++ b/lib/scala/runtime-version-manager/src/main/scala/org/enso/runtimeversionmanager/runner/Project.scala @@ -15,7 +15,7 @@ class Project( ) { /** The edition associated with the project. */ - def edition: Option[Editions.RawEdition] = pkg.config.edition + def edition: Option[Editions.RawEdition] = pkg.getConfig().edition /** The package name of the project. */ def name: String = pkg.name @@ -24,5 +24,5 @@ class Project( def path: Path = pkg.root.toPath /** Project configuration. */ - def config: Config = pkg.config + def config: Config = pkg.getConfig() }