mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 13:02:07 +03:00
When renaming the project clean old modules instead of updating (#6148)
close #6139 close #6137 When the project is renamed, the engine cleans up affected modules and initiates modules re-indexing to fill the suggestions database with new records. This way it reduces the amount of information stored in the suggestions database and helps implement #6080 optimization. Changelog: - remove: rename features from the suggestions database - update: rename command to initiate modules cleanup and project re-execution - fix: #6137
This commit is contained in:
parent
d89de84988
commit
2338e5d8e6
@ -1,11 +0,0 @@
|
||||
package org.enso.languageserver.refactoring
|
||||
|
||||
import org.enso.languageserver.event.Event
|
||||
|
||||
/** An event notifying that project name has changed.
|
||||
*
|
||||
* @param oldName the old name of the project
|
||||
* @param newName the new project name
|
||||
*/
|
||||
case class ProjectNameChangedEvent(oldName: String, newName: String)
|
||||
extends Event
|
@ -5,7 +5,6 @@ import java.util.UUID
|
||||
import akka.actor.{Actor, ActorRef, Cancellable, Props}
|
||||
import com.typesafe.scalalogging.LazyLogging
|
||||
import org.enso.jsonrpc._
|
||||
import org.enso.languageserver.refactoring.ProjectNameChangedEvent
|
||||
import org.enso.languageserver.refactoring.RefactoringApi.RenameProject
|
||||
import org.enso.languageserver.requesthandler.RequestTimeout
|
||||
import org.enso.languageserver.util.UnhandledLogging
|
||||
@ -37,7 +36,6 @@ class RenameProjectHandler(timeout: FiniteDuration, runtimeConnector: ActorRef)
|
||||
context.become(
|
||||
responseStage(
|
||||
id,
|
||||
ProjectNameChangedEvent(params.oldName, params.newName),
|
||||
sender(),
|
||||
cancellable
|
||||
)
|
||||
@ -46,7 +44,6 @@ class RenameProjectHandler(timeout: FiniteDuration, runtimeConnector: ActorRef)
|
||||
|
||||
private def responseStage(
|
||||
id: Id,
|
||||
nameChangedEvent: ProjectNameChangedEvent,
|
||||
replyTo: ActorRef,
|
||||
cancellable: Cancellable
|
||||
): Receive = {
|
||||
@ -56,7 +53,6 @@ class RenameProjectHandler(timeout: FiniteDuration, runtimeConnector: ActorRef)
|
||||
context.stop(self)
|
||||
|
||||
case Api.Response(_, Api.ProjectRenamed(_, _)) =>
|
||||
context.system.eventStream.publish(nameChangedEvent)
|
||||
replyTo ! ResponseResult(RenameProject, id, Unused)
|
||||
cancellable.cancel()
|
||||
context.stop(self)
|
||||
|
@ -23,7 +23,6 @@ import org.enso.languageserver.filemanager.{
|
||||
FileDeletedEvent,
|
||||
Path
|
||||
}
|
||||
import org.enso.languageserver.refactoring.ProjectNameChangedEvent
|
||||
import org.enso.languageserver.runtime.RuntimeFailureMapper
|
||||
import org.enso.languageserver.search.SearchProtocol._
|
||||
import org.enso.languageserver.search.handler.InvalidateModulesIndexHandler
|
||||
@ -36,7 +35,6 @@ import org.enso.polyglot.data.TypeGraph
|
||||
import org.enso.polyglot.runtime.Runtime.Api
|
||||
import org.enso.searcher.data.QueryResult
|
||||
import org.enso.searcher.{SuggestionsRepo, VersionsRepo}
|
||||
import org.enso.text.ContentVersion
|
||||
import org.enso.text.editing.model.Position
|
||||
|
||||
import scala.collection.mutable
|
||||
@ -115,7 +113,6 @@ final class SuggestionsHandler(
|
||||
)
|
||||
context.system.eventStream
|
||||
.subscribe(self, classOf[Api.LibraryLoaded])
|
||||
context.system.eventStream.subscribe(self, classOf[ProjectNameChangedEvent])
|
||||
context.system.eventStream.subscribe(self, classOf[FileDeletedEvent])
|
||||
context.system.eventStream
|
||||
.subscribe(self, InitializedEvent.SuggestionsRepoInitialized.getClass)
|
||||
@ -127,17 +124,6 @@ final class SuggestionsHandler(
|
||||
initializing(SuggestionsHandler.Initialization())
|
||||
|
||||
private def initializing(init: SuggestionsHandler.Initialization): Receive = {
|
||||
case ProjectNameChangedEvent(oldName, newName) =>
|
||||
logger.info(
|
||||
"Initializing: project name changed from [{}] to [{}].",
|
||||
oldName,
|
||||
newName
|
||||
)
|
||||
suggestionsRepo
|
||||
.renameProject(oldName, newName)
|
||||
.map(_ => ProjectNameUpdated(newName))
|
||||
.pipeTo(self)
|
||||
|
||||
case ProjectNameUpdated(name, updates) =>
|
||||
logger.info("Initializing: project name is updated to [{}].", name)
|
||||
updates.foreach(sessionRouter ! _)
|
||||
@ -249,7 +235,7 @@ final class SuggestionsHandler(
|
||||
|
||||
case SuggestionUpdatesBatch(updates) =>
|
||||
val modules = updates.map(_.module)
|
||||
traverseSeq(updates)(applyUpdateIfVersionChanged)
|
||||
traverseSeq(updates)(applyDatabaseUpdates)
|
||||
.onComplete {
|
||||
case Success(results) =>
|
||||
logger.debug(
|
||||
@ -257,17 +243,15 @@ final class SuggestionsHandler(
|
||||
modules.length,
|
||||
modules.mkString(", ")
|
||||
)
|
||||
results.foreach {
|
||||
case Some(notification) =>
|
||||
if (notification.updates.nonEmpty) {
|
||||
clients.foreach { clientId =>
|
||||
sessionRouter ! DeliverToJsonController(
|
||||
clientId,
|
||||
notification
|
||||
)
|
||||
}
|
||||
results.foreach { notification =>
|
||||
if (notification.updates.nonEmpty) {
|
||||
clients.foreach { clientId =>
|
||||
sessionRouter ! DeliverToJsonController(
|
||||
clientId,
|
||||
notification
|
||||
)
|
||||
}
|
||||
case None =>
|
||||
}
|
||||
}
|
||||
self ! SuggestionsHandler.SuggestionUpdatesCompleted
|
||||
case Failure(ex) =>
|
||||
@ -290,9 +274,9 @@ final class SuggestionsHandler(
|
||||
|
||||
case msg: Api.SuggestionsDatabaseModuleUpdateNotification =>
|
||||
logger.debug("Got module update [{}].", msg.module)
|
||||
applyUpdateIfVersionChanged(msg)
|
||||
applyDatabaseUpdates(msg)
|
||||
.onComplete {
|
||||
case Success(Some(notification)) =>
|
||||
case Success(notification) =>
|
||||
logger.debug("Complete module update [{}].", msg.module)
|
||||
if (notification.updates.nonEmpty) {
|
||||
clients.foreach { clientId =>
|
||||
@ -300,12 +284,6 @@ final class SuggestionsHandler(
|
||||
}
|
||||
}
|
||||
self ! SuggestionsHandler.SuggestionUpdatesCompleted
|
||||
case Success(None) =>
|
||||
logger.debug(
|
||||
"Skip module update, version not changed [{}].",
|
||||
msg.module
|
||||
)
|
||||
self ! SuggestionsHandler.SuggestionUpdatesCompleted
|
||||
case Failure(ex) =>
|
||||
logger.error(
|
||||
"Error applying suggestion database updates [{}, {}].",
|
||||
@ -458,55 +436,6 @@ final class SuggestionsHandler(
|
||||
)
|
||||
action.pipeTo(handler)(sender())
|
||||
|
||||
case ProjectNameChangedEvent(oldName, newName) =>
|
||||
suggestionsRepo
|
||||
.renameProject(oldName, newName)
|
||||
.map {
|
||||
case (version, moduleIds, selfTypeIds, returnTypeIds, argumentIds) =>
|
||||
val suggestionModuleUpdates = moduleIds.map {
|
||||
case (suggestionId, moduleName) =>
|
||||
SuggestionsDatabaseUpdate.Modify(
|
||||
id = suggestionId,
|
||||
module = Some(fieldUpdate(moduleName))
|
||||
)
|
||||
}
|
||||
val selfTypeUpdates = selfTypeIds.map {
|
||||
case (suggestionId, selfType) =>
|
||||
SuggestionsDatabaseUpdate.Modify(
|
||||
id = suggestionId,
|
||||
selfType = Some(fieldUpdate(selfType))
|
||||
)
|
||||
}
|
||||
val returnTypeUpdates = returnTypeIds.map {
|
||||
case (suggestionId, returnType) =>
|
||||
SuggestionsDatabaseUpdate.Modify(
|
||||
id = suggestionId,
|
||||
returnType = Some(fieldUpdate(returnType))
|
||||
)
|
||||
}
|
||||
val argumentUpdates =
|
||||
argumentIds.groupBy(_._1).map { case (suggestionId, grouped) =>
|
||||
val argumentUpdates = grouped.map { case (_, index, typeName) =>
|
||||
SuggestionArgumentUpdate.Modify(
|
||||
index = index,
|
||||
reprType = Some(fieldUpdate(typeName))
|
||||
)
|
||||
}
|
||||
SuggestionsDatabaseUpdate.Modify(
|
||||
id = suggestionId,
|
||||
arguments = Some(argumentUpdates)
|
||||
)
|
||||
}
|
||||
val notification =
|
||||
SuggestionsDatabaseUpdateNotification(
|
||||
version,
|
||||
suggestionModuleUpdates ++ selfTypeUpdates ++ returnTypeUpdates ++ argumentUpdates
|
||||
)
|
||||
val updates = clients.map(DeliverToJsonController(_, notification))
|
||||
ProjectNameUpdated(newName, updates)
|
||||
}
|
||||
.pipeTo(self)
|
||||
|
||||
case ProjectNameUpdated(name, updates) =>
|
||||
updates.foreach(sessionRouter ! _)
|
||||
context.become(initialized(name, graph, clients, state))
|
||||
@ -559,19 +488,6 @@ final class SuggestionsHandler(
|
||||
}
|
||||
}
|
||||
|
||||
private def applyUpdateIfVersionChanged(
|
||||
msg: Api.SuggestionsDatabaseModuleUpdateNotification
|
||||
): Future[Option[SuggestionsDatabaseUpdateNotification]] = {
|
||||
val isVersionChanged =
|
||||
versionsRepo.getVersion(msg.module).map { digestOpt =>
|
||||
!digestOpt.map(ContentVersion(_)).contains(msg.version)
|
||||
}
|
||||
isVersionChanged.flatMap { isChanged =>
|
||||
if (isChanged) applyDatabaseUpdates(msg).map(Some(_))
|
||||
else Future.successful(None)
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle the suggestions of the loaded library.
|
||||
*
|
||||
* Adds the new suggestions to the suggestions database and sends the
|
||||
|
@ -11,7 +11,6 @@ import org.enso.languageserver.capability.CapabilityProtocol.{
|
||||
import org.enso.languageserver.data._
|
||||
import org.enso.languageserver.event.InitializedEvent
|
||||
import org.enso.languageserver.filemanager._
|
||||
import org.enso.languageserver.refactoring.ProjectNameChangedEvent
|
||||
import org.enso.languageserver.search.SearchProtocol.SuggestionDatabaseEntry
|
||||
import org.enso.languageserver.session.JsonSession
|
||||
import org.enso.languageserver.session.SessionRouter.DeliverToJsonController
|
||||
@ -745,89 +744,6 @@ class SuggestionsHandlerSpec
|
||||
expectMsg(SearchProtocol.InvalidateSuggestionsDatabaseResult)
|
||||
}
|
||||
|
||||
"rename module when renaming project" taggedAs Retry in withDb {
|
||||
(_, repo, router, _, handler) =>
|
||||
Await.ready(repo.insert(Suggestions.constructor), Timeout)
|
||||
val clientId = UUID.randomUUID()
|
||||
val newModuleName = "Vest"
|
||||
|
||||
// acquire capability
|
||||
handler ! AcquireCapability(
|
||||
newJsonSession(clientId),
|
||||
CapabilityRegistration(ReceivesSuggestionsDatabaseUpdates())
|
||||
)
|
||||
expectMsg(CapabilityAcquired)
|
||||
|
||||
handler ! ProjectNameChangedEvent("Test", newModuleName)
|
||||
|
||||
router.expectMsg(
|
||||
DeliverToJsonController(
|
||||
clientId,
|
||||
SearchProtocol.SuggestionsDatabaseUpdateNotification(
|
||||
2,
|
||||
Seq(
|
||||
SearchProtocol.SuggestionsDatabaseUpdate.Modify(
|
||||
id = 1,
|
||||
module = Some(fieldUpdate("local.Vest.Main"))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
"rename types when renaming project" taggedAs Retry in withDb {
|
||||
(_, repo, router, _, handler) =>
|
||||
val method = Suggestions.method.copy(
|
||||
selfType = "local.Test.MyType",
|
||||
arguments = Suggestions.method.arguments.map(arg =>
|
||||
arg.copy(reprType = "local.Test.MyType")
|
||||
)
|
||||
)
|
||||
Await.ready(repo.insert(method), Timeout)
|
||||
val clientId = UUID.randomUUID()
|
||||
val newModuleName = "Vest"
|
||||
|
||||
// acquire capability
|
||||
handler ! AcquireCapability(
|
||||
newJsonSession(clientId),
|
||||
CapabilityRegistration(ReceivesSuggestionsDatabaseUpdates())
|
||||
)
|
||||
expectMsg(CapabilityAcquired)
|
||||
|
||||
handler ! ProjectNameChangedEvent("Test", newModuleName)
|
||||
|
||||
router.expectMsg(
|
||||
DeliverToJsonController(
|
||||
clientId,
|
||||
SearchProtocol.SuggestionsDatabaseUpdateNotification(
|
||||
2,
|
||||
Seq(
|
||||
SearchProtocol.SuggestionsDatabaseUpdate.Modify(
|
||||
id = 1,
|
||||
module = Some(fieldUpdate("local.Vest.Main"))
|
||||
),
|
||||
SearchProtocol.SuggestionsDatabaseUpdate.Modify(
|
||||
id = 1,
|
||||
selfType = Some(fieldUpdate("local.Vest.MyType"))
|
||||
),
|
||||
SearchProtocol.SuggestionsDatabaseUpdate.Modify(
|
||||
id = 1,
|
||||
arguments = Some(
|
||||
method.arguments.zipWithIndex.map { case (_, index) =>
|
||||
SearchProtocol.SuggestionArgumentUpdate.Modify(
|
||||
index = index,
|
||||
reprType = Some(fieldUpdate("local.Vest.MyType"))
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
"search entries by empty search query" taggedAs Retry in withDb {
|
||||
(config, repo, _, _, handler) =>
|
||||
val (_, inserted) =
|
||||
|
@ -34,9 +34,9 @@ import org.enso.languageserver.protocol.json.{
|
||||
JsonConnectionControllerFactory,
|
||||
JsonRpcProtocolFactory
|
||||
}
|
||||
import org.enso.languageserver.refactoring.ProjectNameChangedEvent
|
||||
import org.enso.languageserver.runtime.{ContextRegistry, RuntimeFailureMapper}
|
||||
import org.enso.languageserver.search.SuggestionsHandler
|
||||
import org.enso.languageserver.search.SuggestionsHandler.ProjectNameUpdated
|
||||
import org.enso.languageserver.session.SessionRouter
|
||||
import org.enso.languageserver.text.BufferRegistry
|
||||
import org.enso.languageserver.vcsmanager.{Git, VcsManager}
|
||||
@ -255,7 +255,7 @@ class BaseServerTest
|
||||
Api.GetTypeGraphResponse(typeGraph)
|
||||
)
|
||||
Await.ready(initializationComponent.init(), timeout)
|
||||
system.eventStream.publish(ProjectNameChangedEvent("Test", "Test"))
|
||||
suggestionsHandler ! ProjectNameUpdated("Test")
|
||||
|
||||
val environment = fakeInstalledEnvironment()
|
||||
val languageHome = LanguageHome.detectFromExecutableLocation(environment)
|
||||
|
@ -3662,9 +3662,29 @@ class RuntimeServerTest
|
||||
context.send(
|
||||
Api.Request(requestId, Api.RenameProject("Enso_Test", "Test", "Foo"))
|
||||
)
|
||||
context.receiveN(1) should contain theSameElementsAs Seq(
|
||||
Api.Response(requestId, Api.ProjectRenamed("Enso_Test", "Foo"))
|
||||
val renameProjectResponses = context.receiveN(6)
|
||||
renameProjectResponses should contain allOf (
|
||||
Api.Response(requestId, Api.ProjectRenamed("Enso_Test", "Foo")),
|
||||
context.Main.Update.mainX(contextId),
|
||||
TestMessages.update(
|
||||
contextId,
|
||||
context.Main.idMainY,
|
||||
ConstantsGen.INTEGER,
|
||||
Api.MethodPointer("Enso_Test.Foo.Main", ConstantsGen.NUMBER, "foo")
|
||||
),
|
||||
context.Main.Update.mainZ(contextId),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
renameProjectResponses.collect {
|
||||
case Api.Response(
|
||||
_,
|
||||
notification: Api.SuggestionsDatabaseModuleUpdateNotification
|
||||
) =>
|
||||
notification.module shouldEqual moduleName
|
||||
notification.actions should contain theSameElementsAs Vector(
|
||||
Api.SuggestionsDatabaseAction.Clean(moduleName)
|
||||
)
|
||||
}
|
||||
|
||||
// recompute existing stack
|
||||
context.send(
|
||||
@ -3707,6 +3727,111 @@ class RuntimeServerTest
|
||||
)
|
||||
}
|
||||
|
||||
it should "push and pop functions after renaming the project" in {
|
||||
val contents = context.Main.code
|
||||
val mainFile = context.writeMain(contents)
|
||||
val moduleName = "Enso_Test.Test.Main"
|
||||
val contextId = UUID.randomUUID()
|
||||
val requestId = UUID.randomUUID()
|
||||
|
||||
// create context
|
||||
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
|
||||
context.receive shouldEqual Some(
|
||||
Api.Response(requestId, Api.CreateContextResponse(contextId))
|
||||
)
|
||||
|
||||
// open file
|
||||
context.send(
|
||||
Api.Request(Api.OpenFileNotification(mainFile, contents))
|
||||
)
|
||||
context.receiveNone shouldEqual None
|
||||
|
||||
// push main
|
||||
val item1 = Api.StackItem.ExplicitCall(
|
||||
Api.MethodPointer(moduleName, moduleName, "main"),
|
||||
None,
|
||||
Vector()
|
||||
)
|
||||
context.send(
|
||||
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
|
||||
)
|
||||
context.receiveNIgnoreStdLib(6) should contain theSameElementsAs Seq(
|
||||
Api.Response(Api.BackgroundJobsStartedNotification()),
|
||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
||||
context.Main.Update.mainX(contextId),
|
||||
context.Main.Update.mainY(contextId),
|
||||
context.Main.Update.mainZ(contextId),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
|
||||
// rename Test -> Foo
|
||||
context.pkg.rename("Foo")
|
||||
context.send(
|
||||
Api.Request(requestId, Api.RenameProject("Enso_Test", "Test", "Foo"))
|
||||
)
|
||||
val renameProjectResponses = context.receiveN(6)
|
||||
renameProjectResponses should contain allOf (
|
||||
Api.Response(requestId, Api.ProjectRenamed("Enso_Test", "Foo")),
|
||||
context.Main.Update.mainX(contextId),
|
||||
TestMessages.update(
|
||||
contextId,
|
||||
context.Main.idMainY,
|
||||
ConstantsGen.INTEGER,
|
||||
Api.MethodPointer("Enso_Test.Foo.Main", ConstantsGen.NUMBER, "foo")
|
||||
),
|
||||
context.Main.Update.mainZ(contextId),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
renameProjectResponses.collect {
|
||||
case Api.Response(
|
||||
_,
|
||||
notification: Api.SuggestionsDatabaseModuleUpdateNotification
|
||||
) =>
|
||||
notification.module shouldEqual moduleName
|
||||
notification.actions should contain theSameElementsAs Vector(
|
||||
Api.SuggestionsDatabaseAction.Clean(moduleName)
|
||||
)
|
||||
}
|
||||
|
||||
// push foo call
|
||||
val item2 = Api.StackItem.LocalCall(context.Main.idMainY)
|
||||
context.send(
|
||||
Api.Request(requestId, Api.PushContextRequest(contextId, item2))
|
||||
)
|
||||
context.receiveNIgnoreStdLib(4) should contain theSameElementsAs Seq(
|
||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
||||
context.Main.Update.fooY(contextId),
|
||||
context.Main.Update.fooZ(contextId),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
|
||||
// pop foo call
|
||||
context.send(Api.Request(requestId, Api.PopContextRequest(contextId)))
|
||||
context.receiveN(3) should contain theSameElementsAs Seq(
|
||||
Api.Response(requestId, Api.PopContextResponse(contextId)),
|
||||
TestMessages.update(
|
||||
contextId,
|
||||
context.Main.idMainY,
|
||||
ConstantsGen.INTEGER,
|
||||
Api.MethodPointer("Enso_Test.Foo.Main", ConstantsGen.NUMBER, "foo"),
|
||||
fromCache = true
|
||||
),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
|
||||
// pop main
|
||||
context.send(Api.Request(requestId, Api.PopContextRequest(contextId)))
|
||||
context.receive shouldEqual Some(
|
||||
Api.Response(requestId, Api.PopContextResponse(contextId))
|
||||
)
|
||||
|
||||
// pop empty stack
|
||||
context.send(Api.Request(requestId, Api.PopContextRequest(contextId)))
|
||||
context.receive shouldEqual Some(
|
||||
Api.Response(requestId, Api.EmptyStackError(contextId))
|
||||
)
|
||||
}
|
||||
|
||||
it should "send the type graph" in {
|
||||
val requestId = UUID.randomUUID()
|
||||
val expectedGraph: TypeGraph = Types.getTypeHierarchy
|
||||
|
@ -698,6 +698,152 @@ class RuntimeSuggestionUpdatesTest
|
||||
context.consumeOut shouldEqual List("51")
|
||||
}
|
||||
|
||||
it should "send suggestion updates after renaming the project" in {
|
||||
val contextId = UUID.randomUUID()
|
||||
val requestId = UUID.randomUUID()
|
||||
val moduleName = "Enso_Test.Test.Main"
|
||||
|
||||
val code =
|
||||
"""from Standard.Base import all
|
||||
|
|
||||
|main = IO.println "Hello World!"
|
||||
|""".stripMargin.linesIterator.mkString("\n")
|
||||
val version = contentsVersion(code)
|
||||
val mainFile = context.writeMain(code)
|
||||
|
||||
// create context
|
||||
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
|
||||
context.receive shouldEqual Some(
|
||||
Api.Response(requestId, Api.CreateContextResponse(contextId))
|
||||
)
|
||||
|
||||
// open file
|
||||
context.send(
|
||||
Api.Request(Api.OpenFileNotification(mainFile, code))
|
||||
)
|
||||
context.receiveNone shouldEqual None
|
||||
|
||||
// push main
|
||||
context.send(
|
||||
Api.Request(
|
||||
requestId,
|
||||
Api.PushContextRequest(
|
||||
contextId,
|
||||
Api.StackItem.ExplicitCall(
|
||||
Api.MethodPointer(moduleName, "Enso_Test.Test.Main", "main"),
|
||||
None,
|
||||
Vector()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
context.receiveNIgnoreExpressionUpdates(
|
||||
4
|
||||
) should contain theSameElementsAs Seq(
|
||||
Api.Response(Api.BackgroundJobsStartedNotification()),
|
||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
||||
Api.Response(
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = moduleName,
|
||||
version = version,
|
||||
actions = Vector(Api.SuggestionsDatabaseAction.Clean(moduleName)),
|
||||
exports = Vector(),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
Api.SuggestionUpdate(
|
||||
Suggestion.Module(
|
||||
moduleName,
|
||||
None
|
||||
),
|
||||
Api.SuggestionAction.Add()
|
||||
),
|
||||
Vector()
|
||||
),
|
||||
Tree.Node(
|
||||
Api.SuggestionUpdate(
|
||||
Suggestion.Method(
|
||||
None,
|
||||
moduleName,
|
||||
"main",
|
||||
List(),
|
||||
"Enso_Test.Test.Main",
|
||||
ConstantsGen.ANY,
|
||||
true,
|
||||
None
|
||||
),
|
||||
Api.SuggestionAction.Add()
|
||||
),
|
||||
Vector()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
context.consumeOut shouldEqual List("Hello World!")
|
||||
|
||||
// rename Test -> Foo
|
||||
context.pkg.rename("Foo")
|
||||
context.send(
|
||||
Api.Request(requestId, Api.RenameProject("Enso_Test", "Test", "Foo"))
|
||||
)
|
||||
context.receiveN(4) should contain theSameElementsAs Seq(
|
||||
Api.Response(requestId, Api.ProjectRenamed("Enso_Test", "Foo")),
|
||||
Api.Response(
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = moduleName,
|
||||
version = version,
|
||||
actions = Vector(Api.SuggestionsDatabaseAction.Clean(moduleName)),
|
||||
exports = Vector(),
|
||||
updates = Tree.empty
|
||||
)
|
||||
),
|
||||
Api.Response(
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = "Enso_Test.Foo.Main",
|
||||
version = version,
|
||||
actions =
|
||||
Vector(Api.SuggestionsDatabaseAction.Clean("Enso_Test.Foo.Main")),
|
||||
exports = Vector(),
|
||||
updates = Tree.Root(
|
||||
Vector(
|
||||
Tree.Node(
|
||||
Api.SuggestionUpdate(
|
||||
Suggestion.Module(
|
||||
"Enso_Test.Foo.Main",
|
||||
None
|
||||
),
|
||||
Api.SuggestionAction.Add()
|
||||
),
|
||||
Vector()
|
||||
),
|
||||
Tree.Node(
|
||||
Api.SuggestionUpdate(
|
||||
Suggestion.Method(
|
||||
None,
|
||||
"Enso_Test.Foo.Main",
|
||||
"main",
|
||||
List(),
|
||||
"Enso_Test.Foo.Main",
|
||||
ConstantsGen.ANY,
|
||||
true,
|
||||
None
|
||||
),
|
||||
Api.SuggestionAction.Add()
|
||||
),
|
||||
Vector()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
context.consumeOut shouldEqual List("Hello World!")
|
||||
}
|
||||
|
||||
it should "index overloaded functions" in {
|
||||
val contextId = UUID.randomUUID()
|
||||
val requestId = UUID.randomUUID()
|
||||
|
@ -109,7 +109,7 @@ class RecomputeContextCmd(
|
||||
val stack = ctx.contextManager.getStack(request.contextId)
|
||||
val executable = Executable(request.contextId, stack)
|
||||
for {
|
||||
_ <- Future(ctx.jobProcessor.run(EnsureCompiledJob(executable.stack)))
|
||||
_ <- ctx.jobProcessor.run(EnsureCompiledJob(executable.stack))
|
||||
_ <- ctx.jobProcessor.run(new ExecuteJob(executable))
|
||||
} yield ()
|
||||
} else {
|
||||
|
@ -1,10 +1,12 @@
|
||||
package org.enso.interpreter.instrument.command
|
||||
|
||||
import java.util.logging.Level
|
||||
|
||||
import org.enso.interpreter.instrument.InstrumentFrame
|
||||
import org.enso.interpreter.instrument.{CacheInvalidation, InstrumentFrame}
|
||||
import org.enso.interpreter.instrument.execution.RuntimeContext
|
||||
import org.enso.interpreter.instrument.job.{EnsureCompiledJob, ExecuteJob}
|
||||
import org.enso.interpreter.runtime.Module
|
||||
import org.enso.pkg.QualifiedName
|
||||
import org.enso.polyglot.data.Tree
|
||||
import org.enso.polyglot.runtime.Runtime.Api
|
||||
|
||||
import scala.collection.mutable
|
||||
@ -25,31 +27,75 @@ class RenameProjectCmd(
|
||||
ctx: RuntimeContext,
|
||||
ec: ExecutionContext
|
||||
): Future[Unit] =
|
||||
Future {
|
||||
ctx.locking.acquireWriteCompilationLock()
|
||||
try {
|
||||
val logger = ctx.executionService.getLogger
|
||||
logger.log(
|
||||
Level.FINE,
|
||||
s"Renaming project [old:${request.namespace}.${request.oldName},new:${request.namespace}.${request.newName}]..."
|
||||
for {
|
||||
_ <- Future { doRename }
|
||||
_ <- reExecute
|
||||
} yield ()
|
||||
|
||||
private def doRename(implicit ctx: RuntimeContext): Unit = {
|
||||
ctx.locking.acquireWriteCompilationLock()
|
||||
try {
|
||||
val logger = ctx.executionService.getLogger
|
||||
logger.log(
|
||||
Level.FINE,
|
||||
s"Renaming project [old:${request.namespace}.${request.oldName},new:${request.namespace}.${request.newName}]..."
|
||||
)
|
||||
val projectModules = getProjectModules
|
||||
projectModules.foreach { module =>
|
||||
module.setIndexed(false)
|
||||
ctx.endpoint.sendToClient(
|
||||
Api.Response(
|
||||
Api.SuggestionsDatabaseModuleUpdateNotification(
|
||||
module = module.getName.toString,
|
||||
version =
|
||||
ctx.versioning.evalVersion(module.getSource.getCharacters),
|
||||
actions = Vector(
|
||||
Api.SuggestionsDatabaseAction.Clean(module.getName.toString)
|
||||
),
|
||||
exports = Vector(),
|
||||
updates = Tree.empty
|
||||
)
|
||||
)
|
||||
)
|
||||
val context = ctx.executionService.getContext
|
||||
context.renameProject(
|
||||
request.namespace,
|
||||
request.oldName,
|
||||
request.newName
|
||||
)
|
||||
ctx.contextManager.getAllContexts.values
|
||||
.foreach(updateMethodPointers(request.newName, _))
|
||||
reply(Api.ProjectRenamed(request.namespace, request.newName))
|
||||
logger.log(
|
||||
Level.INFO,
|
||||
s"Project renamed to ${request.namespace}.${request.newName}"
|
||||
)
|
||||
} finally {
|
||||
ctx.locking.releaseWriteCompilationLock()
|
||||
}
|
||||
|
||||
val context = ctx.executionService.getContext
|
||||
context.renameProject(
|
||||
request.namespace,
|
||||
request.oldName,
|
||||
request.newName
|
||||
)
|
||||
|
||||
ctx.contextManager.getAllContexts.values.foreach { stack =>
|
||||
updateMethodPointers(request.newName, stack)
|
||||
clearCache(stack)
|
||||
}
|
||||
|
||||
reply(Api.ProjectRenamed(request.namespace, request.newName))
|
||||
logger.log(
|
||||
Level.INFO,
|
||||
s"Project renamed to ${request.namespace}.${request.newName}"
|
||||
)
|
||||
} finally {
|
||||
ctx.locking.releaseWriteCompilationLock()
|
||||
}
|
||||
}
|
||||
|
||||
private def reExecute(implicit
|
||||
ctx: RuntimeContext,
|
||||
ec: ExecutionContext
|
||||
): Future[Unit] =
|
||||
for {
|
||||
_ <- Future.sequence {
|
||||
ctx.contextManager.getAllContexts.toVector.map {
|
||||
case (contextId, stack) =>
|
||||
for {
|
||||
_ <- ctx.jobProcessor.run(EnsureCompiledJob(stack))
|
||||
_ <- ctx.jobProcessor.run(new ExecuteJob(contextId, stack.toList))
|
||||
} yield ()
|
||||
}
|
||||
}
|
||||
} yield ()
|
||||
|
||||
/** Update module name of method pointers in the stack.
|
||||
*
|
||||
@ -66,9 +112,33 @@ class RenameProjectCmd(
|
||||
.fromString(call.methodPointer.module)
|
||||
.renameProject(projectName)
|
||||
.toString
|
||||
val methodPointer = call.methodPointer.copy(module = moduleName)
|
||||
val typeName = QualifiedName
|
||||
.fromString(call.methodPointer.definedOnType)
|
||||
.renameProject(projectName)
|
||||
.toString
|
||||
val methodPointer =
|
||||
call.methodPointer.copy(module = moduleName, definedOnType = typeName)
|
||||
InstrumentFrame(call.copy(methodPointer = methodPointer), cache, sync)
|
||||
case item => item
|
||||
}
|
||||
}
|
||||
|
||||
private def getProjectModules(implicit ctx: RuntimeContext): Seq[Module] = {
|
||||
val packageRepository = ctx.executionService.getContext.getPackageRepository
|
||||
packageRepository.getMainProjectPackage
|
||||
.map { pkg => packageRepository.getModulesForLibrary(pkg.libraryName) }
|
||||
.getOrElse(List())
|
||||
}
|
||||
|
||||
private def clearCache(stack: Iterable[InstrumentFrame]): Unit = {
|
||||
stack.foreach(_.syncState.clearMethodPointersState())
|
||||
CacheInvalidation.run(
|
||||
stack,
|
||||
CacheInvalidation(
|
||||
CacheInvalidation.StackSelector.All,
|
||||
CacheInvalidation.Command.InvalidateAll
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -157,24 +157,4 @@ trait SuggestionsRepo[F[_]] {
|
||||
|
||||
/** Cleans the repo resetting the version. */
|
||||
def clean: F[Unit]
|
||||
|
||||
/** Update the suggestions with the new project name.
|
||||
*
|
||||
* @param oldName the old name of the project
|
||||
* @param newName the new project name
|
||||
* @return the current database version and lists of suggestion ids with
|
||||
* updated module name, self type, return type and arguments
|
||||
*/
|
||||
def renameProject(
|
||||
oldName: String,
|
||||
newName: String
|
||||
): F[
|
||||
(
|
||||
Long,
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, Int, String)]
|
||||
)
|
||||
]
|
||||
}
|
||||
|
@ -144,21 +144,6 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
): Future[(Long, Seq[Option[Long]])] =
|
||||
db.run(updateAllQuery(expressions).transactionally)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def renameProject(
|
||||
oldName: String,
|
||||
newName: String
|
||||
): Future[
|
||||
(
|
||||
Long,
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, Int, String)]
|
||||
)
|
||||
] =
|
||||
db.run(renameProjectQuery(oldName, newName).transactionally)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def currentVersion: Future[Long] =
|
||||
db.run(currentVersionQuery)
|
||||
@ -787,73 +772,6 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
|
||||
query
|
||||
}
|
||||
|
||||
/** The query to update the project name.
|
||||
*
|
||||
* @param oldName the old name of the project
|
||||
* @param newName the new project name
|
||||
* @return the current database version and lists of suggestion ids
|
||||
* with updated module name, self type, return type and arguments
|
||||
*/
|
||||
private def renameProjectQuery(
|
||||
oldName: String,
|
||||
newName: String
|
||||
): DBIO[
|
||||
(
|
||||
Long,
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, String)],
|
||||
Seq[(Long, Int, String)]
|
||||
)
|
||||
] = {
|
||||
def updateQuery(column: String) =
|
||||
sqlu"""update suggestions
|
||||
set #$column =
|
||||
substr(#$column, 0, instr(#$column, $oldName)) ||
|
||||
$newName ||
|
||||
substr(#$column, instr(#$column, $oldName) + length($oldName))
|
||||
where #$column like '%.#$oldName.%'"""
|
||||
val argumentsUpdateQuery =
|
||||
sqlu"""update arguments
|
||||
set type =
|
||||
substr(type, 0, instr(type, $oldName)) ||
|
||||
$newName ||
|
||||
substr(type, instr(type, $oldName) + length($oldName))
|
||||
where type like '%.#$oldName.%'"""
|
||||
def noop[A] = DBIO.successful(Seq[A]())
|
||||
|
||||
val selectUpdatedModulesQuery = Suggestions
|
||||
.filter(row => row.module.like(s"%.$newName.%"))
|
||||
.map(row => (row.id, row.module))
|
||||
.result
|
||||
val selectUpdatedSelfTypesQuery = Suggestions
|
||||
.filter(_.selfType.like(s"%.$newName.%"))
|
||||
.map(row => (row.id, row.selfType))
|
||||
.result
|
||||
val selectUpdatedReturnTypesQuery = Suggestions
|
||||
.filter(_.returnType.like(s"%.$newName.%"))
|
||||
.map(row => (row.id, row.returnType))
|
||||
.result
|
||||
val selectUpdatedArgumentsQuery = Arguments
|
||||
.filter(_.tpe.like(s"%.$newName.%"))
|
||||
.map(row => (row.suggestionId, row.index, row.tpe))
|
||||
.result
|
||||
|
||||
for {
|
||||
n1 <- updateQuery("module")
|
||||
moduleIds <- if (n1 > 0) selectUpdatedModulesQuery else noop
|
||||
n2 <- updateQuery("self_type")
|
||||
selfTypeIds <- if (n2 > 0) selectUpdatedSelfTypesQuery else noop
|
||||
n3 <- updateQuery("return_type")
|
||||
returnTypeIds <- if (n3 > 0) selectUpdatedReturnTypesQuery else noop
|
||||
n4 <- argumentsUpdateQuery
|
||||
argumentIds <- if (n4 > 0) selectUpdatedArgumentsQuery else noop
|
||||
version <-
|
||||
if (n1 > 0 || n2 > 0 || n3 > 0 || n4 > 0) incrementVersionQuery
|
||||
else currentVersionQuery
|
||||
} yield (version, moduleIds, selfTypeIds, returnTypeIds, argumentIds)
|
||||
}
|
||||
|
||||
/** The query to get current version of the repo. */
|
||||
private def currentVersionQuery: DBIO[Long] = {
|
||||
for {
|
||||
|
@ -998,279 +998,6 @@ class SuggestionsRepoTest extends AnyWordSpec with Matchers with RetrySpec {
|
||||
v1 shouldEqual v2
|
||||
}
|
||||
|
||||
"rename the project name" taggedAs Retry in withRepo { repo =>
|
||||
val newModuleName = "local.Best.Main"
|
||||
val newSelfType = "local.Best.Main"
|
||||
val newReturnType = "local.Best.Main.MyType"
|
||||
val action = for {
|
||||
(_, ids) <- repo.insertAll(
|
||||
Seq(
|
||||
suggestion.module,
|
||||
suggestion.tpe,
|
||||
suggestion.constructor,
|
||||
suggestion.method,
|
||||
suggestion.conversion,
|
||||
suggestion.function,
|
||||
suggestion.local
|
||||
)
|
||||
)
|
||||
(_, xs1, xs2, xs3, xs4) <- repo.renameProject("Test", "Best")
|
||||
(_, res) <- repo.getAll
|
||||
} yield (ids, xs1, xs2, xs3, xs4, res)
|
||||
|
||||
val (ids, xs1, xs2, xs3, xs4, res) = Await.result(action, Timeout)
|
||||
|
||||
xs1 should contain theSameElementsAs ids.flatten.map((_, newModuleName))
|
||||
xs2 should contain theSameElementsAs Seq(ids(3)).flatten
|
||||
.map((_, newSelfType))
|
||||
xs3 should contain theSameElementsAs Seq(ids(4), ids(5), ids(6)).flatten
|
||||
.map {
|
||||
case id if ids(4).get == id => (id, "local.Best.Main.Bar")
|
||||
case id => (id, newReturnType)
|
||||
}
|
||||
xs4 should contain theSameElementsAs Seq(
|
||||
(ids(4).get, 0, "local.Best.Main.Foo")
|
||||
)
|
||||
res.map(_.suggestion) should contain theSameElementsAs Seq(
|
||||
suggestion.module.copy(module = newModuleName),
|
||||
suggestion.tpe.copy(module = newModuleName),
|
||||
suggestion.constructor.copy(module = newModuleName),
|
||||
suggestion.method
|
||||
.copy(module = newModuleName, selfType = newSelfType),
|
||||
suggestion.conversion.copy(
|
||||
module = newModuleName,
|
||||
sourceType = "local.Best.Main.Foo",
|
||||
returnType = "local.Best.Main.Bar"
|
||||
),
|
||||
suggestion.function
|
||||
.copy(module = newModuleName, returnType = newReturnType),
|
||||
suggestion.local
|
||||
.copy(module = newModuleName, returnType = newReturnType)
|
||||
)
|
||||
}
|
||||
|
||||
"rename the module containing project name" taggedAs Retry in withRepo {
|
||||
repo =>
|
||||
val newModuleName = "local.Best.Main"
|
||||
val newSelfType = "local.Best.Main"
|
||||
val newReturnType = "local.Best.Main.MyType"
|
||||
|
||||
val constructor =
|
||||
suggestion.constructor.copy(module = "local.Test.Main.Test.Main")
|
||||
val all =
|
||||
Seq(
|
||||
suggestion.module,
|
||||
suggestion.tpe,
|
||||
constructor,
|
||||
suggestion.method,
|
||||
suggestion.conversion,
|
||||
suggestion.function,
|
||||
suggestion.local
|
||||
)
|
||||
val action = for {
|
||||
(_, ids) <- repo.insertAll(all)
|
||||
(_, xs1, xs2, xs3, xs4) <- repo.renameProject("Test", "Best")
|
||||
(_, res) <- repo.getAll
|
||||
} yield (ids, xs1, xs2, xs3, xs4, res)
|
||||
|
||||
val (ids, xs1, xs2, xs3, xs4, res) = Await.result(action, Timeout)
|
||||
|
||||
xs1 should contain theSameElementsAs ids.zip(all).flatMap {
|
||||
case (idOpt, _: Suggestion.Constructor) =>
|
||||
idOpt.map((_, "local.Best.Main.Test.Main"))
|
||||
case (idOpt, _) =>
|
||||
idOpt.map((_, newModuleName))
|
||||
}
|
||||
xs2 should contain theSameElementsAs Seq(ids(3)).flatten
|
||||
.map((_, newSelfType))
|
||||
xs3 should contain theSameElementsAs Seq(ids(4), ids(5), ids(6)).flatten
|
||||
.map {
|
||||
case id if ids(4).get == id => (id, "local.Best.Main.Bar")
|
||||
case id => (id, newReturnType)
|
||||
}
|
||||
xs4 should contain theSameElementsAs Seq(
|
||||
(ids(4).get, 0, "local.Best.Main.Foo")
|
||||
)
|
||||
res.map(_.suggestion) should contain theSameElementsAs Seq(
|
||||
suggestion.module.copy(module = newModuleName),
|
||||
suggestion.tpe.copy(module = newModuleName),
|
||||
constructor.copy(module = "local.Best.Main.Test.Main"),
|
||||
suggestion.method
|
||||
.copy(module = newModuleName, selfType = newSelfType),
|
||||
suggestion.conversion.copy(
|
||||
module = newModuleName,
|
||||
sourceType = "local.Best.Main.Foo",
|
||||
returnType = "local.Best.Main.Bar"
|
||||
),
|
||||
suggestion.function
|
||||
.copy(module = newModuleName, returnType = newReturnType),
|
||||
suggestion.local
|
||||
.copy(module = newModuleName, returnType = newReturnType)
|
||||
)
|
||||
}
|
||||
|
||||
"rename multiple modules containing project name" taggedAs Retry in withRepo {
|
||||
repo =>
|
||||
val newMainModuleName = "local.Best.Main"
|
||||
val newFooModuleName = "local.Best.Foo"
|
||||
val newReturnTypeName = "local.Best.Main.MyType"
|
||||
|
||||
val module = suggestion.module.copy(module = "local.Test.Main")
|
||||
val tpe = suggestion.tpe.copy(module = "local.Test.Main")
|
||||
val constructor =
|
||||
suggestion.constructor.copy(module = "local.Test.Main")
|
||||
val method = suggestion.method.copy(module = "local.Test.Foo")
|
||||
val conversion = suggestion.conversion.copy(module = "local.Test.Foo")
|
||||
val function = suggestion.function.copy(module = "local.Bar.Main")
|
||||
val local = suggestion.local.copy(module = "local.Bar.Main")
|
||||
val all =
|
||||
Seq(module, tpe, constructor, method, conversion, function, local)
|
||||
val action = for {
|
||||
(_, ids) <- repo.insertAll(all)
|
||||
(_, xs1, xs2, xs3, xs4) <- repo.renameProject("Test", "Best")
|
||||
(_, res) <- repo.getAll
|
||||
} yield (ids, xs1, xs2, xs3, xs4, res)
|
||||
|
||||
val (ids, xs1, xs2, xs3, xs4, res) = Await.result(action, Timeout)
|
||||
|
||||
xs1 should contain theSameElementsAs ids
|
||||
.zip(Seq(module, tpe, constructor, method, conversion))
|
||||
.flatMap {
|
||||
case (idOpt, _: Suggestion.Module) =>
|
||||
idOpt.map((_, newMainModuleName))
|
||||
case (idOpt, _: Suggestion.Type) =>
|
||||
idOpt.map((_, newMainModuleName))
|
||||
case (idOpt, _: Suggestion.Constructor) =>
|
||||
idOpt.map((_, newMainModuleName))
|
||||
case (idOpt, _) =>
|
||||
idOpt.map((_, newFooModuleName))
|
||||
}
|
||||
xs2 should contain theSameElementsAs Seq(ids(3)).flatten
|
||||
.map((_, newMainModuleName))
|
||||
xs3 should contain theSameElementsAs Seq(ids(4), ids(5), ids(6)).flatten
|
||||
.map {
|
||||
case id if ids(4).get == id => (id, "local.Best.Main.Bar")
|
||||
case id => (id, newReturnTypeName)
|
||||
}
|
||||
xs4 should contain theSameElementsAs Seq(
|
||||
(ids(4).get, 0, "local.Best.Main.Foo")
|
||||
)
|
||||
res.map(_.suggestion) should contain theSameElementsAs Seq(
|
||||
module.copy(module = newMainModuleName),
|
||||
tpe.copy(module = newMainModuleName),
|
||||
constructor.copy(module = newMainModuleName),
|
||||
method.copy(module = newFooModuleName, selfType = newMainModuleName),
|
||||
suggestion.conversion.copy(
|
||||
module = newFooModuleName,
|
||||
sourceType = "local.Best.Main.Foo",
|
||||
returnType = "local.Best.Main.Bar"
|
||||
),
|
||||
function.copy(returnType = newReturnTypeName),
|
||||
local.copy(returnType = newReturnTypeName)
|
||||
)
|
||||
}
|
||||
|
||||
"rename arguments containing project name" taggedAs Retry in withRepo {
|
||||
repo =>
|
||||
val newModuleName = "local.Best.Main"
|
||||
val newSelfType = "local.Best.Main"
|
||||
val newReturnType = "local.Best.Main.MyType"
|
||||
val newArgumentType = "local.Best.Main.Test.MyType"
|
||||
|
||||
val method = suggestion.method.copy(arguments =
|
||||
Seq(
|
||||
Suggestion.Argument("x", "Number", false, true, Some("0")),
|
||||
Suggestion.Argument(
|
||||
"y",
|
||||
"local.Test.Main.Test.MyType",
|
||||
false,
|
||||
false,
|
||||
None
|
||||
)
|
||||
)
|
||||
)
|
||||
val all =
|
||||
Seq(
|
||||
suggestion.module,
|
||||
suggestion.tpe,
|
||||
suggestion.constructor,
|
||||
method,
|
||||
suggestion.conversion,
|
||||
suggestion.function,
|
||||
suggestion.local
|
||||
)
|
||||
val action = for {
|
||||
(_, ids) <- repo.insertAll(all)
|
||||
(_, xs1, xs2, xs3, xs4) <- repo.renameProject("Test", "Best")
|
||||
(_, res) <- repo.getAll
|
||||
} yield (ids, xs1, xs2, xs3, xs4, res)
|
||||
|
||||
val (ids, xs1, xs2, xs3, xs4, res) = Await.result(action, Timeout)
|
||||
|
||||
xs1 should contain theSameElementsAs ids.flatten.map((_, newModuleName))
|
||||
xs2 should contain theSameElementsAs Seq(ids(3)).flatten
|
||||
.map((_, newSelfType))
|
||||
xs3 should contain theSameElementsAs Seq(ids(4), ids(5), ids(6)).flatten
|
||||
.map {
|
||||
case id if ids(4).get == id => (id, "local.Best.Main.Bar")
|
||||
case id => (id, newReturnType)
|
||||
}
|
||||
xs4 should contain theSameElementsAs Seq(ids(3), ids(4)).flatMap {
|
||||
_.map {
|
||||
case id if ids(4).get == id => (id, 0, "local.Best.Main.Foo")
|
||||
case id => (id, 1, newArgumentType)
|
||||
}
|
||||
}
|
||||
res.map(_.suggestion) should contain theSameElementsAs Seq(
|
||||
suggestion.module.copy(module = newModuleName),
|
||||
suggestion.tpe.copy(module = newModuleName),
|
||||
suggestion.constructor.copy(module = newModuleName),
|
||||
method
|
||||
.copy(
|
||||
module = newModuleName,
|
||||
selfType = newSelfType,
|
||||
arguments = method.arguments.map { argument =>
|
||||
argument.copy(reprType =
|
||||
if (argument.reprType.startsWith("local.Test."))
|
||||
newArgumentType
|
||||
else argument.reprType
|
||||
)
|
||||
}
|
||||
),
|
||||
suggestion.conversion.copy(
|
||||
module = newModuleName,
|
||||
sourceType = "local.Best.Main.Foo",
|
||||
returnType = "local.Best.Main.Bar"
|
||||
),
|
||||
suggestion.function
|
||||
.copy(module = newModuleName, returnType = newReturnType),
|
||||
suggestion.local
|
||||
.copy(module = newModuleName, returnType = newReturnType)
|
||||
)
|
||||
}
|
||||
|
||||
"change version after renaming the module" taggedAs Retry in withRepo {
|
||||
repo =>
|
||||
val action = for {
|
||||
v1 <- repo.insert(suggestion.constructor)
|
||||
(v2, _, _, _, _) <- repo.renameProject("Test", "Zest")
|
||||
} yield (v1, v2)
|
||||
|
||||
val (v1, v2) = Await.result(action, Timeout)
|
||||
v1 should not equal Some(v2)
|
||||
}
|
||||
|
||||
"not change version when not renamed the module" taggedAs Retry in withRepo {
|
||||
repo =>
|
||||
val action = for {
|
||||
v1 <- repo.insert(suggestion.constructor)
|
||||
(v2, _, _, _, _) <- repo.renameProject("Zest", "Best")
|
||||
} yield (v1, v2)
|
||||
|
||||
val (v1, v2) = Await.result(action, Timeout)
|
||||
v1 shouldEqual Some(v2)
|
||||
}
|
||||
|
||||
"apply export updates" taggedAs Retry in withRepo { repo =>
|
||||
val reexport = "Foo.Bar"
|
||||
val method = suggestion.method.copy(reexport = Some(reexport))
|
||||
|
Loading…
Reference in New Issue
Block a user