Skip to content

Commit

Permalink
Handle missing bsp info better
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthur McGibbon authored and tgodzik committed Nov 15, 2023
1 parent b48675e commit 9202ed2
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 31 deletions.
Expand Up @@ -94,6 +94,20 @@ class BuildServerConnection private (

def isAmmonite: Boolean = name == Ammonite.name

def supportsLanguage(id: String): Boolean =
Option(capabilities.getCompileProvider())
.exists(_.getLanguageIds().contains(id)) ||
Option(capabilities.getDebugProvider())
.exists(_.getLanguageIds().contains(id)) ||
Option(capabilities.getRunProvider())
.exists(_.getLanguageIds().contains(id)) ||
Option(capabilities.getTestProvider())
.exists(_.getLanguageIds().contains(id))

def supportsScala: Boolean = supportsLanguage("scala")

def supportsJava: Boolean = supportsLanguage("java")

def isDebuggingProvider: Boolean =
Option(capabilities.getDebugProvider())
.exists(_.getLanguageIds().contains("scala"))
Expand Down Expand Up @@ -186,13 +200,38 @@ class BuildServerConnection private (
def mainClasses(
params: ScalaMainClassesParams
): Future[ScalaMainClassesResult] = {
register(server => server.buildTargetScalaMainClasses(params)).asScala
val resultOnUnsupported = new ScalaMainClassesResult(Collections.emptyList)
if (supportsScala) {
val onFail = Some(
(
resultOnUnsupported,
"Scala main classes not supported by server",
)
)
register(
server => server.buildTargetScalaMainClasses(params),
onFail,
).asScala
} else Future.successful(resultOnUnsupported)

}

def testClasses(
params: ScalaTestClassesParams
): Future[ScalaTestClassesResult] = {
register(server => server.buildTargetScalaTestClasses(params)).asScala
val resultOnUnsupported = new ScalaTestClassesResult(Collections.emptyList)
if (supportsScala) {
val onFail = Some(
(
resultOnUnsupported,
"Scala test classes not supported by server",
)
)
register(
server => server.buildTargetScalaTestClasses(params),
onFail,
).asScala
} else Future.successful(resultOnUnsupported)
}

def startDebugSession(
Expand Down Expand Up @@ -240,13 +279,18 @@ class BuildServerConnection private (
)
if (isSbt || isAmmonite) Future.successful(resultOnJavacOptionsUnsupported)
else {
val onFail = Some(
(
resultOnJavacOptionsUnsupported,
"Java targets not supported by server",
if (supportsJava) {
val onFail = Some(
(
resultOnJavacOptionsUnsupported,
"Java targets not supported by server",
)
)
)
register(server => server.buildTargetJavacOptions(params), onFail).asScala
register(
server => server.buildTargetJavacOptions(params),
onFail,
).asScala
} else Future.successful(resultOnJavacOptionsUnsupported)
}
}

Expand All @@ -256,10 +300,18 @@ class BuildServerConnection private (
val resultOnScalaOptionsUnsupported = new ScalacOptionsResult(
List.empty[ScalacOptionsItem].asJava
)
val onFail = Some(
(resultOnScalaOptionsUnsupported, "Scala targets not supported by server")
)
register(server => server.buildTargetScalacOptions(params), onFail).asScala
if (supportsScala) {
val onFail = Some(
(
resultOnScalaOptionsUnsupported,
"Scala targets not supported by server",
)
)
register(
server => server.buildTargetScalacOptions(params),
onFail,
).asScala
} else Future.successful(resultOnScalaOptionsUnsupported)
}

def buildTargetSources(params: SourcesParams): Future[SourcesResult] = {
Expand Down
Expand Up @@ -14,7 +14,7 @@ class BuildTargetInfo(buildTargets: BuildTargets) {

def buildTargetDetails(targetName: String, uri: String): String = {
buildTargets.all
.find(_.getDisplayName == targetName)
.find(_.getName == targetName)
.orElse(buildTargets.all.find(_.getId.getUri.toString == uri))
.map(target => buildTargetDetail(target.getId()))
.getOrElse(s"Build target $targetName not found")
Expand All @@ -32,7 +32,7 @@ class BuildTargetInfo(buildTargets: BuildTargets) {

commonInfo.foreach(info => {
output += "Target"
output += s" ${info.getDisplayName}"
output += s" ${info.getName}"

if (!info.getTags.isEmpty)
output ++= getSection("Tags", info.getTags.asScala.toList)
Expand Down Expand Up @@ -91,7 +91,10 @@ class BuildTargetInfo(buildTargets: BuildTargets) {
"Scala Binary Version",
List(info.scalaBinaryVersion),
)
output ++= getSection("Scala Platform", List(info.scalaPlatform))
output ++= getSection(
"Scala Platform",
List(info.scalaPlatform.toString()),
)
info.jvmVersion.foreach(jvmVersion =>
output ++= getSection("JVM Version", List(jvmVersion))
)
Expand Down Expand Up @@ -136,18 +139,19 @@ class BuildTargetInfo(buildTargets: BuildTargets) {

private def getSection(
sectionName: String,
sectionText: List[_],
sectionText: List[String],
): List[String] =
"" :: sectionName :: {
if (sectionText.isEmpty) List(" NONE")
else sectionText.map(text => s" $text")
else
sectionText.map(text => s" ${if (text.isEmpty) "[BLANK]" else text}")
}

private def translateCapability(
capability: String,
hasCapability: Boolean,
): String =
if (hasCapability) s" $capability" else s" $capability <- NOT SUPPORTED"
if (hasCapability) capability else s"$capability <- NOT SUPPORTED"

private def jarHasSource(jarName: String): Boolean = {
val sourceJarName = jarName.replace(".jar", "-sources.jar")
Expand Down Expand Up @@ -194,15 +198,15 @@ class BuildTargetInfo(buildTargets: BuildTargets) {
)
)
} else
List(" NONE")
List("NONE")
}

private def getDependencies(target: BuildTarget): List[String] = {
target.getDependencies.asScala
.map(f =>
buildTargets
.info(f)
.map(_.getDisplayName())
.map(_.getName())
.getOrElse("Unknown target")
)
.toList
Expand All @@ -213,7 +217,7 @@ class BuildTargetInfo(buildTargets: BuildTargets) {
.filter(dependentTarget =>
dependentTarget.getDependencies.contains(target.getId())
)
.map(_.getDisplayName())
.map(_.getName())
.toList
}

Expand Down
Expand Up @@ -16,7 +16,7 @@ case class JavaTarget(
javac: JavacOptionsItem,
bspConnection: Option[BuildServerConnection],
) {
def displayName: String = info.getDisplayName()
def displayName: String = info.getName

def dataKind: String = info.dataKind

Expand Down
Expand Up @@ -88,6 +88,8 @@ object MetalsEnrichments

def isSbtBuild: Boolean = dataKind == "sbt"

def isScalaBuild: Boolean = dataKind == "scala"

def baseDirectory: String =
Option(buildTarget.getBaseDirectory()).getOrElse("")

Expand All @@ -96,7 +98,11 @@ object MetalsEnrichments
def asScalaBuildTarget: Option[b.ScalaBuildTarget] = {
asSbtBuildTarget
.map(_.getScalaBuildTarget)
.orElse(decodeJson(buildTarget.getData, classOf[b.ScalaBuildTarget]))
.orElse(
if (isScalaBuild)
decodeJson(buildTarget.getData, classOf[b.ScalaBuildTarget])
else None
)
}

def asSbtBuildTarget: Option[b.SbtBuildTarget] = {
Expand All @@ -105,6 +111,22 @@ object MetalsEnrichments
else
None
}

def getName(): String = {
if (buildTarget.getDisplayName == null) {
val name =
if (buildTarget.getBaseDirectory() != null)
buildTarget
.getId()
.getUri()
.stripPrefix(buildTarget.getBaseDirectory())
else
buildTarget.getId().getUri()

name.replaceAll("[^a-zA-Z0-9]+", "-")
} else
buildTarget.getDisplayName
}
}

implicit class XtensionTaskStart(task: b.TaskStartParams) {
Expand Down
Expand Up @@ -52,7 +52,7 @@ case class ScalaTarget(
}
}

def displayName: String = info.getDisplayName()
def displayName: String = info.getName

def dataKind: String = info.dataKind

Expand Down
Expand Up @@ -141,8 +141,10 @@ final class TargetData {
}

def targetClassDirectories(id: BuildTargetIdentifier): List[String] = {
val scalacData = scalaTarget(id).map(_.scalac.getClassDirectory).toList
val javacData = javaTarget(id).map(_.javac.getClassDirectory).toList
val scalacData =
scalaTarget(id).map(_.scalac.getClassDirectory).filter(_.nonEmpty).toList
val javacData =
javaTarget(id).map(_.javac.getClassDirectory).filter(_.nonEmpty).toList
(scalacData ++ javacData).distinct
}

Expand Down
Expand Up @@ -532,7 +532,7 @@ final class Doctor(
javaTarget.displayName,
gotoBuildTargetCommand(workspace, javaTarget.displayName),
javaTarget.dataKind,
javaTarget.baseDirectory,
Option(javaTarget.baseDirectory),
"Java",
compilationStatus,
diagnosticsStatus,
Expand Down Expand Up @@ -612,7 +612,7 @@ final class Doctor(
scalaTarget.displayName,
gotoBuildTargetCommand(workspace, scalaTarget.displayName),
scalaTarget.dataKind,
scalaTarget.baseDirectory,
Option(scalaTarget.baseDirectory),
targetType,
compilationStatus,
diagnosticsStatus,
Expand Down
Expand Up @@ -66,7 +66,7 @@ final case class DoctorTargetInfo(
name: String,
gotoCommand: String,
dataKind: String,
baseDirectory: String,
baseDirectory: Option[String],
targetType: String,
compilationStatus: DoctorStatus,
diagnosticsStatus: DoctorStatus,
Expand Down
Expand Up @@ -293,7 +293,7 @@ class FolderTreeViewProvider(
_.getId(),
_.getUri(),
uri => new BuildTargetIdentifier(uri),
_.getDisplayName(),
_.getName(),
_.baseDirectory,
{ () =>
buildTargets.all.filter(target =>
Expand Down Expand Up @@ -447,7 +447,7 @@ class FolderTreeViewProvider(
} yield TreeViewNode(
TreeViewProvider.Compile,
id.getUri,
s"${info.getDisplayName()} - ${compilation.timer.toStringSeconds} (${compilation.progressPercentage}%)",
s"${info.getName()} - ${compilation.timer.toStringSeconds} (${compilation.progressPercentage}%)",
icon = "compile",
)
}
Expand Down
1 change: 1 addition & 0 deletions tests/unit/src/main/scala/bill/Bill.scala
Expand Up @@ -140,6 +140,7 @@ object Bill {
)
result.setDisplayName("id")
result.setData(scalaTarget)
result.setDataKind("scala")
result
}
val reporter = new StoreReporter
Expand Down
Expand Up @@ -108,6 +108,7 @@ object MetalsTestEnrichments {
val gson = new Gson
val data = gson.toJsonTree(scalaTarget)
buildTarget.setData(data)
buildTarget.setDataKind("scala")
val result = new WorkspaceBuildTargetsResult(List(buildTarget).asJava)
val data0 = new m.internal.metals.TargetData
data0.addWorkspaceBuildTargets(result)
Expand Down

0 comments on commit 9202ed2

Please sign in to comment.