Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvement: convert workspace folder to be a Metals project on chosen commands #7135

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also include .bsp ?

Copy link
Contributor Author

@kasiaMarek kasiaMarek Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a Scala thing, so I added it too.

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
Loading