-
Notifications
You must be signed in to change notification settings - Fork 338
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
improvement: add debug adapter for running main class to metals
- Loading branch information
1 parent
99f098a
commit a641cf6
Showing
9 changed files
with
523 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
metals/src/main/scala/scala/meta/internal/metals/debug/server/DebugLogger.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package scala.meta.internal.metals.debug.server | ||
|
||
import ch.epfl.scala.debugadapter.Logger | ||
|
||
class DebugLogger extends Logger { | ||
|
||
override def debug(msg: => String): Unit = scribe.debug(msg) | ||
|
||
override def info(msg: => String): Unit = scribe.info(msg) | ||
|
||
override def warn(msg: => String): Unit = scribe.warn(msg) | ||
|
||
override def error(msg: => String): Unit = scribe.error(msg) | ||
|
||
override def trace(t: => Throwable): Unit = | ||
scribe.trace(s"$t: ${t.getStackTrace().mkString("\n\t")}") | ||
|
||
} |
134 changes: 134 additions & 0 deletions
134
metals/src/main/scala/scala/meta/internal/metals/debug/server/DebugeeParamsCreator.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package scala.meta.internal.metals.debug.server | ||
|
||
import java.nio.file.Path | ||
|
||
import scala.concurrent.ExecutionContext | ||
import scala.concurrent.Future | ||
import scala.concurrent.Promise | ||
|
||
import scala.meta.internal.metals.BuildTargets | ||
import scala.meta.internal.metals.JavaTarget | ||
import scala.meta.internal.metals.MetalsEnrichments._ | ||
import scala.meta.internal.metals.ScalaTarget | ||
|
||
import ch.epfl.scala.bsp4j.BuildTargetIdentifier | ||
import ch.epfl.scala.bsp4j.MavenDependencyModule | ||
import ch.epfl.scala.debugadapter.Library | ||
import ch.epfl.scala.debugadapter.Module | ||
import ch.epfl.scala.debugadapter.ScalaVersion | ||
import ch.epfl.scala.debugadapter.SourceDirectory | ||
import ch.epfl.scala.debugadapter.SourceJar | ||
import ch.epfl.scala.debugadapter.UnmanagedEntry | ||
|
||
class DebugeeParamsCreator(buildTargets: BuildTargets)(implicit | ||
ec: ExecutionContext | ||
) { | ||
def create(id: BuildTargetIdentifier): Option[Future[DebugeeProject]] = { | ||
val optScalaTarget = buildTargets.scalaTarget(id) | ||
val optJavaTarget = buildTargets.javaTarget(id) | ||
for { | ||
name <- optScalaTarget | ||
.map(_.displayName) | ||
.orElse(optJavaTarget.map(_.displayName)) | ||
data <- buildTargets.targetData(id) | ||
} yield { | ||
|
||
val libraries = data.buildTargetDependencyModules | ||
.get(id) | ||
.filter(_.nonEmpty) | ||
.getOrElse(Nil) | ||
val debugLibs = libraries.flatMap(createLibrary(_)) | ||
val includedInLibs = debugLibs | ||
.flatMap(_.sourceEntries.flatMap { | ||
case SourceJar(jar) => Some(jar) | ||
case _ => None | ||
}) | ||
.toSet | ||
|
||
val cancelPromise: Promise[Unit] = Promise() | ||
|
||
for ( | ||
classpath <- buildTargets | ||
.targetClasspath(id, cancelPromise) | ||
.getOrElse(Future.successful(Nil)) | ||
.map(_.toAbsoluteClasspath.map(_.toNIO).toSeq) | ||
) yield { | ||
|
||
val filteredClassPath = classpath.collect { | ||
case path if includedInLibs(path) => UnmanagedEntry(path) | ||
}.toList | ||
|
||
val modules = buildTargets | ||
.allInverseDependencies(id) | ||
.flatMap(id => | ||
buildTargets.scalaTarget(id).map(createModule(_)).orElse { | ||
buildTargets.javaTarget(id).map(createModule(_)) | ||
} | ||
) | ||
.toSeq | ||
|
||
new DebugeeProject( | ||
buildTargets.scalaTarget(id).map(_.scalaVersion), | ||
name, | ||
modules, | ||
libraries.flatMap(createLibrary(_)), | ||
filteredClassPath, | ||
classpath, | ||
) | ||
} | ||
} | ||
} | ||
|
||
def createLibrary(lib: MavenDependencyModule): Option[Library] = { | ||
def getWithClassifier(s: String) = | ||
Option(lib.getArtifacts()) | ||
.flatMap(_.asScala.find(_.getClassifier() == s)) | ||
.flatMap(_.getUri().toAbsolutePathSafe) | ||
for { | ||
sources <- getWithClassifier("sources") | ||
jar <- getWithClassifier(null) | ||
} yield new Library( | ||
lib.getName(), | ||
lib.getVersion(), | ||
jar.toNIO, | ||
Seq(SourceJar(sources.toNIO)), | ||
) | ||
} | ||
|
||
def createModule(target: ScalaTarget): Module = { | ||
val scalaVersion = ScalaVersion(target.scalaVersion) | ||
new Module( | ||
target.displayName, | ||
Some(scalaVersion), | ||
target.scalac.getOptions().asScala.toSeq, | ||
target.classDirectory.toAbsolutePath.toNIO, | ||
sources(target.id), | ||
) | ||
} | ||
|
||
def createModule(target: JavaTarget) = | ||
new Module( | ||
target.displayName, | ||
None, | ||
Nil, | ||
target.classDirectory.toAbsolutePath.toNIO, | ||
sources(target.id), | ||
) | ||
|
||
private def sources(id: BuildTargetIdentifier) = | ||
buildTargets.sourceItemsToBuildTargets | ||
.filter(_._2.iterator.asScala.contains(id)) | ||
.collect { case (path, _) => | ||
SourceDirectory(path.toNIO) | ||
} | ||
.toSeq | ||
} | ||
|
||
case class DebugeeProject( | ||
scalaVersion: Option[String], | ||
name: String, | ||
modules: Seq[Module], | ||
libraries: Seq[Library], | ||
unmanagedEntries: Seq[UnmanagedEntry], | ||
classpath: Seq[Path], | ||
) |
Oops, something went wrong.