Skip to content

Commit

Permalink
feat: add custom project root setting
Browse files Browse the repository at this point in the history
  • Loading branch information
kasiaMarek committed Oct 20, 2023
1 parent fb4b251 commit cf13700
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 18 deletions.
45 changes: 32 additions & 13 deletions metals/src/main/scala/scala/meta/internal/builds/BuildTools.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,40 @@ final class BuildTools(
)
def isBazel: Boolean = bazelProject.isDefined

private def customProjectRoot =
userConfig().customProjectRoot
.map(_.trim() match {
case "." => workspace
case relativePath => workspace.resolve(relativePath)
})
.filter { projectRoot =>
val exists = projectRoot.exists
if (!exists) {
scribe.error(s"custom project root $projectRoot does not exist")
}
exists
}

private def searchForBuildTool(
isProjectRoot: AbsolutePath => Boolean
): Option[AbsolutePath] =
if (isProjectRoot(workspace)) Some(workspace)
else
workspace.toNIO
.toFile()
.listFiles()
.collectFirst {
case file
if file.isDirectory &&
!file.getName.startsWith(".") &&
isProjectRoot(AbsolutePath(file.toPath())) =>
AbsolutePath(file.toPath())
}
): Option[AbsolutePath] = {
customProjectRoot match {
case Some(projectRoot) => Some(projectRoot).filter(isProjectRoot)
case None =>
if (isProjectRoot(workspace)) Some(workspace)
else
workspace.toNIO
.toFile()
.listFiles()
.collectFirst {
case file
if file.isDirectory &&
!file.getName.startsWith(".") &&
isProjectRoot(AbsolutePath(file.toPath())) =>
AbsolutePath(file.toPath())
}
}
}

def allAvailable: List[BuildTool] = {
List(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,13 @@ class MetalsLspService(
compilers.restartAll()
}

val slowConnect =
if (userConfig.customProjectRoot != old.customProjectRoot) {
tables.buildTool.reset()
tables.buildServers.reset()
slowConnectToBuildServer(false).ignoreValue
} else Future.successful(())

val resetDecorations =
if (
userConfig.showImplicitArguments != old.showImplicitArguments ||
Expand Down Expand Up @@ -1008,11 +1015,10 @@ class MetalsLspService(
}
.getOrElse(Future.successful(()))

Future
.sequence(
List(restartBuildServer, resetDecorations)
)
.map(_ => ())
for {
_ <- slowConnect
_ <- Future.sequence(List(restartBuildServer, resetDecorations))
} yield ()
}

override def didOpen(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ case class UserConfiguration(
testUserInterface: TestUserInterfaceKind = TestUserInterfaceKind.CodeLenses,
javaFormatConfig: Option[JavaFormatConfig] = None,
scalafixRulesDependencies: List[String] = Nil,
customProjectRoot: Option[String] = None,
scalaCliLauncher: Option[String] = None,
) {

Expand Down Expand Up @@ -313,6 +314,14 @@ object UserConfiguration {
|launcher, not available in PATH.
|""".stripMargin,
),
UserConfigurationOption(
"custom-project-root",
"""empty string `""`.""",
""""backend/scalaProject/"""",
"Scala CLI launcher",
"""Optional relative path to your project's root.
|If you want your project root to be the workspace/workspace root set it to "." .""".stripMargin,
),
)

def fromJson(
Expand Down Expand Up @@ -525,6 +534,8 @@ object UserConfiguration {
val scalafixRulesDependencies =
getStringListKey("scalafix-rules-dependencies").getOrElse(Nil)

val customProjectRoot = getStringKey("custom-project-root")

if (errors.isEmpty) {
Right(
UserConfiguration(
Expand Down Expand Up @@ -555,6 +566,7 @@ object UserConfiguration {
disableTestCodeLenses,
javaFormatConfig,
scalafixRulesDependencies,
customProjectRoot,
)
)
} else {
Expand Down
37 changes: 37 additions & 0 deletions tests/slow/src/test/scala/tests/CustomProjectRootLspSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package tests
import scala.meta.internal.metals.UserConfiguration
import scala.meta.internal.metals.{BuildInfo => V}

class CustomProjectRootLspSuite
extends BaseLspSuite("custom-project-root", BloopImportInitializer) {
override def userConfig: UserConfiguration =
UserConfiguration().copy(customProjectRoot = Some("inner/inner/"))

test("basic") {
cleanWorkspace()
for {
_ <- initialize(
s"""|/build.sbt
|scalaVersion := "${V.scala213}"
|/inner/inner/project.scala
|//> using scala ${V.scala3}
|/inner/inner/Main.scala
|package a
|
|val k = 1
|val m: Int = "aaa"
|""".stripMargin
)
_ <- server.didOpen("inner/inner/Main.scala")
_ = assert(server.server.bspSession.exists(_.main.isScalaCLI))
_ = assertEquals(
client.workspaceDiagnostics,
"""|inner/inner/Main.scala:4:14: error: Found: ("aaa" : String)
|Required: Int
|val m: Int = "aaa"
| ^^^^^
|""".stripMargin,
)
} yield ()
}
}

0 comments on commit cf13700

Please sign in to comment.