diff --git a/docs/language-server/protocol-language-server.md b/docs/language-server/protocol-language-server.md index a2994fa88f85..b3ecba33c4ee 100644 --- a/docs/language-server/protocol-language-server.md +++ b/docs/language-server/protocol-language-server.md @@ -57,6 +57,7 @@ transport formats, please look [here](./protocol-architecture). - [`WorkspaceEdit`](#workspaceedit) - [`EnsoDigest`](#ensodigest) - [`FileSegment`](#filesegment) + - [`ContentRoot`](#contentroot) - [Connection Management](#connection-management) - [`session/initProtocolConnection`](#sessioninitprotocolconnection) - [`session/initBinaryConnection`](#sessioninitbinaryconnection) @@ -1156,34 +1157,60 @@ a location on a real file-system that has been virtualised for use in the Enso VFS. ```typescript -interface ContentRoot { +type ContentRoot = Project | FileSystemRoot | Home | Library | Custom; +``` + +```typescript +/** This content root points to the project home. */ +interface Project { // A unique identifier for the content root. id: UUID; - // The type of content root. - type: ContentRootType; +} - // The name of the content root. - name: String; +/** + * This content root points to the system root (`/`) on unix systems, or to a + * drive root on Windows. In Windows' case, there may be multiple `Root` entries + * corresponding to the various drives. + */ +interface FileSystemRoot { + // A unique identifier for the content root. + id: UUID; + + // The absolute filesystem path of the content root. + path: String; } -``` -### `ContentRootType` +/** The user's home directory. */ +interface Home { + // A unique identifier for the content root. + id: UUID; +} -The type of the annotated content root. +/** An Enso library location. */ +interface Library { + // A unique identifier for the content root. + id: UUID; -```typescript -type ContentRootType = Project | Root | Home | Library | Custom; -``` + // The namespace of the library. + namespace: String; -These represent: + // The name of the library. + name: String; + + /** + * The version of the library. + * + * It is either a semver version of the library or the string "local". + */ + version: String; +} -- `Project`: This content root points to the project home. -- `Root`: This content root points to the system root (`/`) on unix systems, or - to a drive root on Windows. In Windows' case, there may be multiple `Root` - entries corresponding to the various drives. -- `Home`: The user's home directory. -- `Library`: An Enso library location. -- `Custom`: A content root that has been added by the IDE (unused for now). +/** A content root that has been added by the IDE (unused for now). */ +interface Custom { + // A unique identifier for the content root. + id: UUID; +} +``` ## Connection Management diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala b/engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala index 7b84acf8b1f0..f0be586938da 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala @@ -9,10 +9,10 @@ import org.enso.languageserver.capability.CapabilityRouter import org.enso.languageserver.data._ import org.enso.languageserver.effect.ZioExec import org.enso.languageserver.filemanager.{ + ContentRoot, ContentRootManager, ContentRootManagerActor, ContentRootManagerWrapper, - ContentRootType, ContentRootWithFile, FileManager, FileSystem, @@ -62,9 +62,7 @@ class MainModule(serverConfig: LanguageServerConfig, logLevel: LogLevel) { val directoriesConfig = ProjectDirectoriesConfig(serverConfig.contentRootPath) private val contentRoot = ContentRootWithFile( - serverConfig.contentRootUuid, - ContentRootType.Project, - "Project", + ContentRoot.Project(serverConfig.contentRootUuid), new File(serverConfig.contentRootPath) ) val languageServerConfig = Config( diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/filemanager/ContentRoot.scala b/engine/language-server/src/main/scala/org/enso/languageserver/filemanager/ContentRoot.scala index e352a96841b1..bca912a8eb8b 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/filemanager/ContentRoot.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/filemanager/ContentRoot.scala @@ -1,69 +1,128 @@ package org.enso.languageserver.filemanager -import enumeratum._ +import io.circe.syntax.EncoderOps +import io.circe.{Encoder, Json} import java.io.File import java.util.UUID -/** A representation of a content root. - * - * @param id the unique identifier of the content root - * @param type the type of the content root - * @param name The name of the content root - */ -case class ContentRoot(id: UUID, `type`: ContentRootType, name: String) +/** A representation of a content root. */ +sealed trait ContentRoot { -/** The type of entity that the content root represents. - */ -sealed trait ContentRootType extends EnumEntry -object ContentRootType extends Enum[ContentRootType] with CirceEnum[ContentRootType] { + /** The unique identifier of the content root. */ + def id: UUID +} - /** The content root represents the root of the current Enso project. +object ContentRoot { + + /** A filesystem root. + * + * @param id the unique identifier of the content root + * @param path absolute path of the content root */ - case object Project extends ContentRootType + case class FileSystemRoot(override val id: UUID, path: String) + extends ContentRoot - /** The content root represents a system root (`/` on unix, drives on - * windows). + /** A root representing user's home on the filesystem. * - * There may be multiple of this type of root sent by default. + * @param id the unique identifier of the content root */ - case object Root extends ContentRootType + case class Home(override val id: UUID) extends ContentRoot - /** The content root represents the user's home directory. + /** Main project root. + * + * @param id the unique identifier of the content root */ - case object Home extends ContentRootType + case class Project(override val id: UUID) extends ContentRoot - /** The content root represents an Enso library. + /** A root of an imported library. + * + * @param id the unique identifier of the content root + * @param namespace namespace of the library + * @param name name of the library + * @param version version of the library */ - case object Library extends ContentRootType + case class Library( + override val id: UUID, + namespace: String, + name: String, + version: String + ) extends ContentRoot - /** The content root was a custom location added by the IDE. + /** A custom root, currently not used. + * + * @param id the unique identifier of the content root */ - case object Custom extends ContentRootType + case class Custom(override val id: UUID) extends ContentRoot + + private object CodecField { + val Id = "id" + val Type = "type" + val Namespace = "namespace" + val Name = "name" + val Version = "version" + val Path = "path" + } + + private object CodecType { + val FileSystemRoot = "FileSystemRoot" + val Home = "Home" + val Project = "Project" + val Library = "Library" + val Custom = "Custom" + } - /** Necessary for Enumeratum and Circe. */ - override val values = findValues + /** An [[Encoder]] instance for [[ContentRoot]]. */ + implicit val encoder: Encoder[ContentRoot] = { + case FileSystemRoot(id, path) => + Json.obj( + CodecField.Type -> CodecType.FileSystemRoot.asJson, + CodecField.Id -> id.asJson, + CodecField.Path -> path.asJson + ) + case Home(id) => + Json.obj( + CodecField.Type -> CodecType.Home.asJson, + CodecField.Id -> id.asJson + ) + case Project(id) => + Json.obj( + CodecField.Type -> CodecType.Project.asJson, + CodecField.Id -> id.asJson + ) + case Library(id, namespace, name, version) => + Json.obj( + CodecField.Type -> CodecType.Library.asJson, + CodecField.Id -> id.asJson, + CodecField.Namespace -> namespace.asJson, + CodecField.Name -> name.asJson, + CodecField.Version -> version.asJson + ) + case Custom(id) => + Json.obj( + CodecField.Type -> CodecType.Custom.asJson, + CodecField.Id -> id.asJson + ) + } } -/** A representation of a content root. +/** A representation of a content root with a file that represents its + * filesystem location * - * @param id the unique identifier of the content root - * @param `type` the type of the content root - * @param name The name of the content root + * @param contentRoot the raw content root * @param file the file on the filesystem that is the content root */ case class ContentRootWithFile( - id: UUID, - `type`: ContentRootType, - name: String, + contentRoot: ContentRoot, file: File ) { + /** The unique identifier of the content root. */ + def id: UUID = contentRoot.id + /** Convert this to a content root for use in the protocol. * * @return a protocol content root */ - def toContentRoot: ContentRoot = { - ContentRoot(id, `type`, name) - } + def toContentRoot: ContentRoot = contentRoot } diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/filemanager/ContentRootManagerActor.scala b/engine/language-server/src/main/scala/org/enso/languageserver/filemanager/ContentRootManagerActor.scala index d6dd998aa817..ddea074e15dc 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/filemanager/ContentRootManagerActor.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/filemanager/ContentRootManagerActor.scala @@ -58,13 +58,14 @@ class ContentRootManagerActor(config: Config) context.become(mainStage(contentRoots, subscribers + sender())) case Api.LibraryLoaded(libraryName, libraryVersion, rootPath) => - val rootName = s"$libraryName:$libraryVersion" - val libraryRoot = ContentRootWithFile( - id = UUID.randomUUID(), - `type` = ContentRootType.Library, - name = rootName, - file = rootPath.getCanonicalFile + ContentRoot.Library( + id = UUID.randomUUID(), + namespace = libraryName.namespace, + name = libraryName.name, + version = libraryVersion.toString + ), + file = rootPath.getCanonicalFile ) subscribers.foreach { subscriber => @@ -109,7 +110,7 @@ object ContentRootManagerActor { private case class ContentRoots( projectRoot: ContentRootWithFile, librariesRoots: List[ContentRootWithFile], - homeRoots: List[ContentRootWithFile], + homeRoot: Option[ContentRootWithFile], filesystemRoots: List[ContentRootWithFile] ) { def addLibraryRoot(contentRoot: ContentRootWithFile): ContentRoots = @@ -122,7 +123,7 @@ object ContentRootManagerActor { * roots will take precedence. */ lazy val toList: List[ContentRootWithFile] = - List(projectRoot) ++ librariesRoots ++ homeRoots ++ filesystemRoots + List(projectRoot) ++ librariesRoots ++ homeRoot.toList ++ filesystemRoots /** Resolves the path as relative to one of the registered content roots. * @@ -146,13 +147,12 @@ object ContentRootManagerActor { val fsRoots = FileSystems.getDefault.getRootDirectories.asScala.map { path => val absolutePath = path.toAbsolutePath.normalize - val name = - Option(absolutePath.getRoot).map(_.toString).getOrElse("") ContentRootWithFile( - id = UUID.randomUUID(), - `type` = ContentRootType.Root, - name = name, - file = absolutePath.toFile + ContentRoot.FileSystemRoot( + id = UUID.randomUUID(), + path = absolutePath.toString + ), + file = absolutePath.toFile ) } @@ -160,16 +160,14 @@ object ContentRootManagerActor { homeProp <- sys.props.get("user.home") homePath <- Try(JPath.of(homeProp)).toOption } yield ContentRootWithFile( - id = UUID.randomUUID(), - `type` = ContentRootType.Home, - name = "Home", - file = homePath.toAbsolutePath.normalize.toFile + ContentRoot.Home(UUID.randomUUID()), + file = homePath.toAbsolutePath.normalize.toFile ) ContentRoots( projectRoot = config.projectContentRoot, librariesRoots = Nil, - homeRoots = homeRoot.toList, + homeRoot = homeRoot, filesystemRoots = fsRoots.toList ) } diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/protocol/json/JsonConnectionController.scala b/engine/language-server/src/main/scala/org/enso/languageserver/protocol/json/JsonConnectionController.scala index 5d3e145944c4..be3adba01c1d 100644 --- a/engine/language-server/src/main/scala/org/enso/languageserver/protocol/json/JsonConnectionController.scala +++ b/engine/language-server/src/main/scala/org/enso/languageserver/protocol/json/JsonConnectionController.scala @@ -207,7 +207,11 @@ class JsonConnectionController( ): Receive = { case ContentRootManagerProtocol.ContentRootsAddedNotification(roots) => val allRoots = roots ++ rootsSoFar - if (roots.exists(_.`type` == ContentRootType.Project)) { + val hasProject = roots.exists { + case ContentRootWithFile(ContentRoot.Project(_), _) => true + case _ => false + } + if (hasProject) { cancellable.cancel() unstashAll() diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/boot/resource/RepoInitializationSpec.scala b/engine/language-server/src/test/scala/org/enso/languageserver/boot/resource/RepoInitializationSpec.scala index fe4f92f27b30..4c21a1a56488 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/boot/resource/RepoInitializationSpec.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/boot/resource/RepoInitializationSpec.scala @@ -5,10 +5,7 @@ import akka.testkit._ import org.apache.commons.io.FileUtils import org.enso.languageserver.data._ import org.enso.languageserver.event.InitializedEvent -import org.enso.languageserver.filemanager.{ - ContentRootType, - ContentRootWithFile -} +import org.enso.languageserver.filemanager.{ContentRoot, ContentRootWithFile} import org.enso.searcher.sql.{ SchemaVersion, SqlDatabase, @@ -222,9 +219,7 @@ class RepoInitializationSpec sys.addShutdownHook(FileUtils.deleteQuietly(testContentRoot.toFile)) val config = newConfig( ContentRootWithFile( - UUID.randomUUID(), - ContentRootType.Project, - "Project", + ContentRoot.Project(UUID.randomUUID()), testContentRoot.toFile ) ) diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/filemanager/ContentRootManagerSpec.scala b/engine/language-server/src/test/scala/org/enso/languageserver/filemanager/ContentRootManagerSpec.scala index 34a082f5ba5a..81a9aaf94289 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/filemanager/ContentRootManagerSpec.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/filemanager/ContentRootManagerSpec.scala @@ -33,9 +33,7 @@ class ContentRootManagerSpec def makeContentRootManager(): (ContentRootManagerWrapper, ActorRef) = { val root = ContentRootWithFile( - UUID.randomUUID(), - ContentRootType.Project, - "Project", + ContentRoot.Project(UUID.randomUUID()), new File("foobar").getCanonicalFile ) val config = Config( @@ -57,17 +55,17 @@ class ContentRootManagerSpec val (contentRootManager, _) = makeContentRootManager() val roots = contentRootManager.getContentRoots(system.dispatcher).futureValue - val simplifiedRoots = - roots.map(root => (root.name, root.`type`, root.file)) + val fsRoots = + roots.collect { + case ContentRootWithFile(ContentRoot.FileSystemRoot(_, path), _) => + path + } if (SystemUtils.IS_OS_WINDOWS) { - simplifiedRoots should contain( - ("C:\\", ContentRootType.Root, new File("C:\\")) - ) + fsRoots should contain("C:\\") } else { - simplifiedRoots should contain( - ("/", ContentRootType.Root, new File("/")) - ) + fsRoots should contain("/") + fsRoots should have size 1 } } @@ -79,15 +77,19 @@ class ContentRootManagerSpec inside(subscriberProbe.receiveOne(2.seconds.dilated)) { case ContentRootsAddedNotification(roots) => - val projectRoot = roots.filter(_.`type` == ContentRootType.Project) - projectRoot should have size 1 - roots.filter(_.`type` == ContentRootType.Root) should not be empty + val projectRoots = roots.collect { + case ContentRootWithFile(ContentRoot.Project(_), _) => + } + val fsRoots = roots.collect { + case ContentRootWithFile(ContentRoot.Project(_), _) => + } + projectRoots should have size 1 + fsRoots should not be empty } val libraryName = LibraryName("Foo", "Bar") val libraryVersion = LibraryVersion.Local val rootPath = new File("foobar") - val rootName = "Foo.Bar:local" system.eventStream.publish( Api.LibraryLoaded(libraryName, libraryVersion, rootPath) @@ -97,13 +99,27 @@ class ContentRootManagerSpec case ContentRootsAddedNotification(roots) => roots should have length 1 val root = roots.head - root.name shouldEqual rootName - root.file.getCanonicalFile shouldEqual rootPath.getCanonicalFile - root.`type` shouldEqual ContentRootType.Library + inside(root) { + case ContentRootWithFile( + ContentRoot.Library(_, namespace, name, version), + file + ) => + file.getCanonicalFile shouldEqual rootPath.getCanonicalFile + namespace shouldEqual "Foo" + name shouldEqual "Bar" + version shouldEqual "local" + } } val roots = wrapper.getContentRoots(system.dispatcher).futureValue - roots.map(r => r.name) should contain(rootName) + roots.exists { + case ContentRootWithFile( + ContentRoot.Library(_, "Foo", "Bar", "local"), + _ + ) => + true + case _ => false + } } "return the root based on the id" in { @@ -124,8 +140,15 @@ class ContentRootManagerSpec import system.dispatcher val roots = rootManager.getContentRoots.futureValue - val projectRoot = roots.filter(_.`type` == ContentRootType.Project).head - val fsRoot = roots.filter(_.`type` == ContentRootType.Root).head + val projectRoots = roots.collect { + case root @ ContentRootWithFile(ContentRoot.Project(_), _) => root + } + val fsRoots = roots.collect { + case root @ ContentRootWithFile(ContentRoot.Project(_), _) => root + } + + val projectRoot = projectRoots.head + val someFsRoot = fsRoots.head val projectPathRel = JPath.of("p1/foo") val projectPathAbsolute = @@ -137,10 +160,10 @@ class ContentRootManagerSpec val fsPathRel = JPath.of("fs/bar") val fsPathAbsolute = - fsRoot.file.toPath.resolve(fsPathRel).toFile + someFsRoot.file.toPath.resolve(fsPathRel).toFile val fsPathResolved = rootManager.findRelativePath(fsPathAbsolute).futureValue.value - fsPathResolved.rootId shouldEqual fsRoot.id + fsPathResolved.rootId shouldEqual someFsRoot.id fsPathResolved.segments shouldEqual Vector("fs", "bar") } } diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/filemanager/ContentRootSerializationSpec.scala b/engine/language-server/src/test/scala/org/enso/languageserver/filemanager/ContentRootSerializationSpec.scala new file mode 100644 index 000000000000..7fee59ebab0b --- /dev/null +++ b/engine/language-server/src/test/scala/org/enso/languageserver/filemanager/ContentRootSerializationSpec.scala @@ -0,0 +1,53 @@ +package org.enso.languageserver.filemanager + +import io.circe.Json +import io.circe.syntax._ +import io.circe.literal._ +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec + +import java.util.UUID + +class ContentRootSerializationSpec extends AnyWordSpec with Matchers { + "ContentRoot" should { + "correctly serialize" in { + val id = UUID.randomUUID() + + def toJson(contentRoot: ContentRoot): Json = contentRoot.asJson + + toJson(ContentRoot.FileSystemRoot(id, path = "/")) shouldEqual + json"""{ + "type": "FileSystemRoot", + "id": $id, + "path": "/" + }""" + + toJson(ContentRoot.Project(id)) shouldEqual + json"""{ + "type": "Project", + "id": $id + }""" + + toJson(ContentRoot.Home(id)) shouldEqual + json"""{ + "type": "Home", + "id": $id + }""" + + toJson(ContentRoot.Library(id, "foo", "Bar", "baz")) shouldEqual + json"""{ + "type": "Library", + "id": $id, + "namespace": "foo", + "name": "Bar", + "version": "baz" + }""" + + toJson(ContentRoot.Custom(id)) shouldEqual + json"""{ + "type": "Custom", + "id": $id + }""" + } + } +} diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/runtime/ContextEventsListenerSpec.scala b/engine/language-server/src/test/scala/org/enso/languageserver/runtime/ContextEventsListenerSpec.scala index ea519c96ffaf..5152e4e73dee 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/runtime/ContextEventsListenerSpec.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/runtime/ContextEventsListenerSpec.scala @@ -6,10 +6,10 @@ import org.apache.commons.io.FileUtils import org.enso.languageserver.data._ import org.enso.languageserver.event.InitializedEvent import org.enso.languageserver.filemanager.{ + ContentRoot, ContentRootManager, ContentRootManagerActor, ContentRootManagerWrapper, - ContentRootType, ContentRootWithFile } import org.enso.languageserver.runtime.ContextRegistryProtocol._ @@ -474,9 +474,7 @@ class ContextEventsListenerSpec sys.addShutdownHook(FileUtils.deleteQuietly(testContentRoot.toFile)) val config = newConfig( ContentRootWithFile( - UUID.randomUUID(), - ContentRootType.Project, - "Project", + ContentRoot.Project(UUID.randomUUID()), testContentRoot.toFile ) ) diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/search/SuggestionsHandlerSpec.scala b/engine/language-server/src/test/scala/org/enso/languageserver/search/SuggestionsHandlerSpec.scala index dde964def01e..4ba3f1574a40 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/search/SuggestionsHandlerSpec.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/search/SuggestionsHandlerSpec.scala @@ -1,8 +1,5 @@ package org.enso.languageserver.search -import java.io.File -import java.nio.file.Files -import java.util.UUID import akka.actor.{ActorRef, ActorSystem} import akka.testkit.{ImplicitSender, TestKit, TestProbe} import org.apache.commons.io.FileUtils @@ -12,14 +9,7 @@ import org.enso.languageserver.capability.CapabilityProtocol.{ } import org.enso.languageserver.data._ import org.enso.languageserver.event.InitializedEvent -import org.enso.languageserver.filemanager.{ - ContentRootManager, - ContentRootManagerActor, - ContentRootManagerWrapper, - ContentRootType, - ContentRootWithFile, - Path -} +import org.enso.languageserver.filemanager._ import org.enso.languageserver.refactoring.ProjectNameChangedEvent import org.enso.languageserver.search.SearchProtocol.SuggestionDatabaseEntry import org.enso.languageserver.session.JsonSession @@ -36,6 +26,9 @@ import org.scalatest.BeforeAndAfterAll import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike +import java.io.File +import java.nio.file.Files +import java.util.UUID import scala.concurrent.duration._ import scala.concurrent.{Await, Future} import scala.util.{Failure, Success} @@ -839,9 +832,7 @@ class SuggestionsHandlerSpec sys.addShutdownHook(FileUtils.deleteQuietly(testContentRoot.toFile)) val config = newConfig( ContentRootWithFile( - UUID.randomUUID(), - ContentRootType.Project, - "Project", + ContentRoot.Project(UUID.randomUUID()), testContentRoot.toFile ) ) diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/binary/BaseBinaryServerTest.scala b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/binary/BaseBinaryServerTest.scala index 10edcf2b9625..035210e80204 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/binary/BaseBinaryServerTest.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/binary/BaseBinaryServerTest.scala @@ -15,10 +15,10 @@ import org.enso.languageserver.data.{ } import org.enso.languageserver.effect.ZioExec import org.enso.languageserver.filemanager.{ + ContentRoot, ContentRootManager, ContentRootManagerActor, ContentRootManagerWrapper, - ContentRootType, ContentRootWithFile, FileManager, FileSystem @@ -37,9 +37,7 @@ class BaseBinaryServerTest extends BinaryServerTestKit { val testContentRootId = UUID.randomUUID() val testContentRoot = ContentRootWithFile( - testContentRootId, - ContentRootType.Project, - "Project", + ContentRoot.Project(testContentRootId), Files.createTempDirectory(null).toRealPath().toFile ) val config = Config( diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/BaseServerTest.scala b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/BaseServerTest.scala index 7f5a17dee13b..464bcda78be9 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/BaseServerTest.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/BaseServerTest.scala @@ -2,6 +2,8 @@ package org.enso.languageserver.websocket.json import akka.testkit.TestProbe import io.circe.literal._ +import io.circe.parser.parse +import io.circe.syntax.EncoderOps import org.apache.commons.io.FileUtils import org.enso.jsonrpc.test.JsonRpcServerTestKit import org.enso.jsonrpc.{ClientControllerFactory, Protocol} @@ -14,16 +16,7 @@ import org.enso.languageserver.capability.CapabilityRouter import org.enso.languageserver.data._ import org.enso.languageserver.effect.ZioExec import org.enso.languageserver.event.InitializedEvent -import org.enso.languageserver.filemanager.{ - ContentRootManager, - ContentRootManagerActor, - ContentRootManagerWrapper, - ContentRootType, - ContentRootWithFile, - FileManager, - FileSystem, - ReceivesTreeUpdatesHandler -} +import org.enso.languageserver.filemanager._ import org.enso.languageserver.io._ import org.enso.languageserver.protocol.json.{ JsonConnectionControllerFactory, @@ -37,16 +30,14 @@ import org.enso.languageserver.text.BufferRegistry import org.enso.polyglot.data.TypeGraph import org.enso.polyglot.runtime.Runtime.Api import org.enso.searcher.sql.{SqlDatabase, SqlSuggestionsRepo, SqlVersionsRepo} +import org.enso.testkit.EitherValue import org.enso.text.Sha3_224VersionCalculator +import org.scalatest.OptionValues import java.nio.file.Files import java.util.UUID import scala.concurrent.Await import scala.concurrent.duration._ -import io.circe.parser.parse -import io.circe.syntax.EncoderOps -import org.enso.testkit.EitherValue -import org.scalatest.OptionValues class BaseServerTest extends JsonRpcServerTestKit @@ -59,9 +50,7 @@ class BaseServerTest val testContentRootId = UUID.randomUUID() val testContentRoot = ContentRootWithFile( - testContentRootId, - ContentRootType.Project, - "Project", + ContentRoot.Project(testContentRootId), Files.createTempDirectory(null).toRealPath().toFile ) val config = mkConfig @@ -250,8 +239,7 @@ class BaseServerTest json""" { "id" : $testContentRootId, - "type" : "Project", - "name" : "Project" + "type" : "Project" } """ ) diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/FileManagerTest.scala b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/FileManagerTest.scala index d734c22bec09..720806dc7a0a 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/FileManagerTest.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/FileManagerTest.scala @@ -1799,8 +1799,6 @@ class FileManagerTest extends BaseServerTest with RetrySpec { val libraryName = LibraryName("Foo", "Bar") val libraryVersion = LibraryVersion.Published(SemVer(1, 2, 3), repo) val rootPath = new File("foobar") - val rootName = "Foo.Bar:1.2.3" - system.eventStream.publish( Api.LibraryLoaded(libraryName, libraryVersion, rootPath) ) @@ -1809,8 +1807,10 @@ class FileManagerTest extends BaseServerTest with RetrySpec { inside(parsed) { case Right(json) => val params = json.asObject.value("params").value.asObject.value val root = params("root").value.asObject.value - root("name").value.asString.value shouldEqual rootName root("type").value.asString.value shouldEqual "Library" + root("namespace").value.asString.value shouldEqual "Foo" + root("name").value.asString.value shouldEqual "Bar" + root("version").value.asString.value shouldEqual "1.2.3" } } } diff --git a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/SessionManagementTest.scala b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/SessionManagementTest.scala index 6f910bf62b52..05bdb840ffaf 100644 --- a/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/SessionManagementTest.scala +++ b/engine/language-server/src/test/scala/org/enso/languageserver/websocket/json/SessionManagementTest.scala @@ -30,8 +30,7 @@ class SessionManagementTest extends BaseServerTest { json""" { "id" : $testContentRootId, - "type" : "Project", - "name" : "Project" + "type" : "Project" } """ ) diff --git a/lib/scala/editions/src/main/scala/org/enso/editions/LibraryName.scala b/lib/scala/editions/src/main/scala/org/enso/editions/LibraryName.scala index 77379b0d4a95..14377baf068c 100644 --- a/lib/scala/editions/src/main/scala/org/enso/editions/LibraryName.scala +++ b/lib/scala/editions/src/main/scala/org/enso/editions/LibraryName.scala @@ -4,14 +4,16 @@ import io.circe.{Decoder, DecodingFailure} /** Represents a library name that should uniquely identify the library. * - * The prefix is either a special prefix or a username. + * @param namespace library's namespace - either a special reserved prefix or + * the username of the main author + * @param name library's name */ -case class LibraryName(prefix: String, name: String) { +case class LibraryName(namespace: String, name: String) { /** The qualified name of the library consists of its prefix and name * separated with a dot. */ - def qualifiedName: String = s"$prefix.$name" + def qualifiedName: String = s"$namespace.$name" /** @inheritdoc */ override def toString: String = qualifiedName diff --git a/lib/scala/editions/src/test/scala/org/enso/editions/LibraryNameSpec.scala b/lib/scala/editions/src/test/scala/org/enso/editions/LibraryNameSpec.scala index e7ff1686dc76..29e42439905e 100644 --- a/lib/scala/editions/src/test/scala/org/enso/editions/LibraryNameSpec.scala +++ b/lib/scala/editions/src/test/scala/org/enso/editions/LibraryNameSpec.scala @@ -17,7 +17,7 @@ class LibraryNameSpec val libraryName = LibraryName.fromString(str).rightValue libraryName.qualifiedName shouldEqual str libraryName.name shouldEqual "Bar" - libraryName.prefix shouldEqual "Foo" + libraryName.namespace shouldEqual "Foo" val yamlParsed = YamlHelper.parseString[LibraryName](str).rightValue yamlParsed shouldEqual libraryName diff --git a/lib/scala/library-manager/src/main/scala/org/enso/librarymanager/local/DefaultLocalLibraryProvider.scala b/lib/scala/library-manager/src/main/scala/org/enso/librarymanager/local/DefaultLocalLibraryProvider.scala index b2a164298735..52c891e7ea73 100644 --- a/lib/scala/library-manager/src/main/scala/org/enso/librarymanager/local/DefaultLocalLibraryProvider.scala +++ b/lib/scala/library-manager/src/main/scala/org/enso/librarymanager/local/DefaultLocalLibraryProvider.scala @@ -28,7 +28,7 @@ class DefaultLocalLibraryProvider(distributionManager: DistributionManager) searchPaths: List[Path] ): Option[Path] = searchPaths match { case head :: tail => - val potentialPath = head / libraryName.prefix / libraryName.name + val potentialPath = head / libraryName.namespace / libraryName.name if (Files.exists(potentialPath) && Files.isDirectory(potentialPath)) Some(potentialPath) else findLibraryHelper(libraryName, tail)