Skip to content

Commit

Permalink
improvement: convert workspace folder to be a Metals project on chose…
Browse files Browse the repository at this point in the history
…n commands (#7135)
  • Loading branch information
kasiaMarek authored Jan 31, 2025
1 parent 1f7cae4 commit edd5d12
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,10 @@ object MetalsEnrichments
def isScalaProject(): Boolean =
containsProjectFilesSatisfying(_.isScala)
def isMetalsProject(): Boolean =
containsProjectFilesSatisfying(_.isScalaOrJavaFilename)
path.resolve(".metals").exists ||
path.resolve(".bloop").exists ||
path.resolve(".bsp").exists ||
containsProjectFilesSatisfying(_.isScalaOrJavaFilename)

private def containsProjectFilesSatisfying(
fileNamePredicate: String => Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class WorkspaceFolders(
} yield ()
}

def convertToScalaProject(folder: Folder): Option[MetalsLspService] = {
def convertToScalaProject(folder: Folder): Option[ProjectMetalsLspService] = {
val WorkspaceFoldersServices(after, _) =
folderServices.updateAndGet {
case wfs @ WorkspaceFoldersServices(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,17 +330,40 @@ class WorkspaceLspService(
def onCurrentFolder[A](
f: ProjectMetalsLspService => Future[A],
actionName: String,
forceMetalsProject: Boolean,
default: () => A,
): Future[A] = {
def forcedFocusedToBeMetalsProject(): Option[ProjectMetalsLspService] =
nonScalaProjects match {
case Nil => None
case head :: Nil if folderServices.isEmpty =>
workspaceFolders.convertToScalaProject(head)
case _ =>
focusedDocument
.get()
.flatMap(getFolderForOpt(_, nonScalaProjects))
.flatMap(workspaceFolders.convertToScalaProject)
}
def currentService(): Future[Option[ProjectMetalsLspService]] =
folderServices match {
case Nil if forceMetalsProject =>
Future { forcedFocusedToBeMetalsProject() }
case Nil => Future { None }
case head :: Nil => Future { Some(head) }
case _ =>
case head :: rest =>
focusedDocument.get().flatMap(getServiceForOpt) match {
case Some(service) => Future { Some(service) }
case None =>
workspaceChoicePopup.interactiveChooseFolder(actionName)
if (rest.isEmpty) {
Future { Some(head) }
} else if (forceMetalsProject) {
forcedFocusedToBeMetalsProject()
.map(folder => Future.successful(Some(folder)))
.getOrElse(
workspaceChoicePopup.interactiveChooseFolder(actionName)
)
} else {
workspaceChoicePopup.interactiveChooseFolder(actionName)
}
}
}
currentService().flatMap {
Expand All @@ -358,8 +381,9 @@ class WorkspaceLspService(
def onCurrentFolder(
f: ProjectMetalsLspService => Future[Unit],
actionName: String,
forceMetalsProject: Boolean = false,
): Future[Unit] =
onCurrentFolder(f, actionName, () => ())
onCurrentFolder(f, actionName, forceMetalsProject, () => ())

def foreachSeq[A](
f: ProjectMetalsLspService => Future[A],
Expand Down Expand Up @@ -774,18 +798,21 @@ class WorkspaceLspService(
onCurrentFolder(
_.generateBspConfig(),
ServerCommands.GenerateBspConfig.title,
forceMetalsProject = true,
).asJavaObject
case ServerCommands.ImportBuild() =>
onCurrentFolder(
_.connectionProvider.slowConnectToBuildServer(forceImport = true),
ServerCommands.ImportBuild.title,
default = () => BuildChange.None,
forceMetalsProject = true,
).asJavaObject
case ServerCommands.ConnectBuildServer() =>
onCurrentFolder(
_.connectionProvider.quickConnectToBuildServer(),
ServerCommands.ConnectBuildServer.title,
default = () => BuildChange.None,
forceMetalsProject = true,
).asJavaObject
case ServerCommands.DisconnectBuildServer() =>
onCurrentFolder(
Expand Down Expand Up @@ -1380,8 +1407,7 @@ class Folder(
) {

lazy val isMetalsProject: Boolean =
isKnownMetalsProject || path.resolve(".metals").exists || path
.isMetalsProject()
isKnownMetalsProject || path.isMetalsProject()

/**
* A workspace folder might be a project reference for an other project.
Expand Down
32 changes: 32 additions & 0 deletions tests/slow/src/test/scala/tests/gradle/GradleLspSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,38 @@ class GradleLspSuite extends BaseImportSuite("gradle-import") {
}
}

test("i7031") {
cleanWorkspace()
for {
_ <- initialize(
Map(
"root" -> s"""|/build.gradle
|plugins {
| id 'scala'
|}
|repositories {
| mavenCentral()
|}
|dependencies {
| implementation 'org.scala-lang:scala-library:${V.scala213}'
|}
|""".stripMargin
),
expectError = false,
)
_ <- server.fullServer
.executeCommand(ServerCommands.ImportBuild.toExecuteCommandParams())
.asScala
} yield {
assert(server.fullServer.folderServices.nonEmpty)
assert(
server.headServer.tables.buildTool
.selectedBuildTool()
.exists(_ == GradleBuildTool.name)
)
}
}

test("inner") {
client.importBuild = ImportBuild.yes
cleanWorkspace()
Expand Down

0 comments on commit edd5d12

Please sign in to comment.