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 (e.g. import build)

also assume, that workspace folder is Metals project if it contains `.bloop` folder
  • Loading branch information
kasiaMarek committed Jan 20, 2025
1 parent 716ecb9 commit 97a4f7f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,9 @@ object MetalsEnrichments
def isScalaProject(): Boolean =
containsProjectFilesSatisfying(_.isScala)
def isMetalsProject(): Boolean =
containsProjectFilesSatisfying(_.isScalaOrJavaFilename)
path.resolve(".metals").exists ||
path.resolve(".bloop").exists ||
containsProjectFilesSatisfying(_.isScalaOrJavaFilename)

private def containsProjectFilesSatisfying(
fileNamePredicate: String => Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,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 @@ -329,17 +329,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 @@ -357,8 +380,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 @@ -773,18 +797,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 @@ -1379,8 +1406,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 97a4f7f

Please sign in to comment.