Skip to content

Commit 8eee69a

Browse files
author
builduser
committed
Merged branch idea251.release into idea251.x
2 parents 47e508a + 5196556 commit 8eee69a

File tree

4 files changed

+98
-28
lines changed

4 files changed

+98
-28
lines changed

scala/compile-server/src/org/jetbrains/jps/incremental/scala/remote/Main.scala

+57-12
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import org.jetbrains.plugins.scala.compiler.data.{Arguments, ComputeStampsArgume
1212
import org.jetbrains.plugins.scala.server.CompileServerToken
1313

1414
import java.io.{IOException, PrintStream}
15-
import java.lang.reflect.Method
1615
import java.net.URLClassLoader
1716
import java.nio.charset.StandardCharsets
1817
import java.nio.file.{Files, Path}
@@ -226,23 +225,69 @@ object Main {
226225
server.compileDocument(arguments, client)
227226
}
228227

229-
private val expressionCompilerCache: Cache[Seq[Path], (AnyRef, Method)] = new Cache(3)
228+
private val classLoaderCache: Cache[Seq[Path], ClassLoader] = new Cache(3)
230229

231230
private def evaluateExpressionLogic(args: ExpressionEvaluationArguments, client: Client): Unit = {
232-
val ExpressionEvaluationArguments(outDir, classpath, scalacOptions, source, line, expression, localVariableNames, packageName) = args
233-
234-
val (instance, method) = expressionCompilerCache.getOrUpdate(classpath) { () =>
235-
val classLoader = new URLClassLoader(classpath.map(_.toUri.toURL).toArray, this.getClass.getClassLoader)
236-
val bridgeClass = Class.forName("dotty.tools.dotc.ExpressionCompilerBridge", true, classLoader)
237-
val instance = bridgeClass.getDeclaredConstructor().newInstance().asInstanceOf[AnyRef]
238-
val method = bridgeClass.getMethods.find(_.getName == "run").get
239-
(instance, method)
231+
val ExpressionEvaluationArguments(useBuiltInExpressionCompiler, outDir, classpath, scalacOptions, source, line, expression, localVariableNames, packageName) = args
232+
233+
val classLoader = classLoaderCache.getOrUpdate(classpath) { () =>
234+
new URLClassLoader(classpath.map(_.toUri.toURL).toArray, this.getClass.getClassLoader)
240235
}
241236

237+
val bridgeClassName =
238+
if (useBuiltInExpressionCompiler) "dotty.tools.debug.ExpressionCompilerBridge"
239+
else "dotty.tools.dotc.ExpressionCompilerBridge"
240+
241+
val bridgeClass = Class.forName(bridgeClassName, true, classLoader)
242+
val bridgeInstance = bridgeClass.getDeclaredConstructor().newInstance().asInstanceOf[AnyRef]
243+
val runMethod = bridgeClass.getMethods.find(_.getName == "run").get
244+
242245
val consumer: java.util.function.Consumer[String] = client.error(_)
246+
val expressionClassName = "CompiledExpression"
247+
val classpathString = classpath.mkString(java.io.File.pathSeparator)
248+
val scalacOptionsArray = scalacOptions.toArray
249+
val localVariableNamesJavaSet = localVariableNames.asJava
250+
251+
if (useBuiltInExpressionCompiler) {
252+
val config = assembleExpressionCompilerConfig(classLoader, packageName, expressionClassName, line, expression, localVariableNamesJavaSet, consumer)
253+
runMethod.invoke(bridgeInstance, outDir, classpathString, scalacOptionsArray, source, config)
254+
} else {
255+
runMethod.invoke(bridgeInstance, outDir, expressionClassName, classpathString, scalacOptionsArray, source, line,
256+
expression, localVariableNamesJavaSet, packageName, consumer, true)
257+
}
258+
}
259+
260+
private def assembleExpressionCompilerConfig(
261+
classLoader: ClassLoader,
262+
packageName: String,
263+
outputClassName: String,
264+
breakpointLine: Int,
265+
expression: String,
266+
localVariables: java.util.Set[String],
267+
errorReporter: java.util.function.Consumer[String]
268+
): AnyRef = {
269+
val configClass = Class.forName("dotty.tools.debug.ExpressionCompilerConfig", true, classLoader)
270+
var configInstance = configClass.getDeclaredConstructor().newInstance().asInstanceOf[AnyRef]
271+
272+
val withPackageNameMethod = configClass.getDeclaredMethod("withPackageName", classOf[String])
273+
configInstance = withPackageNameMethod.invoke(configInstance, packageName)
274+
275+
val withOutputClassNameMethod = configClass.getDeclaredMethod("withOutputClassName", classOf[String])
276+
configInstance = withOutputClassNameMethod.invoke(configInstance, outputClassName)
277+
278+
val withBreakpointLineMethod = configClass.getDeclaredMethod("withBreakpointLine", classOf[Int])
279+
configInstance = withBreakpointLineMethod.invoke(configInstance, breakpointLine)
280+
281+
val withExpressionMethod = configClass.getDeclaredMethod("withExpression", classOf[String])
282+
configInstance = withExpressionMethod.invoke(configInstance, expression)
283+
284+
val withLocalVariablesMethod = configClass.getDeclaredMethod("withLocalVariables", classOf[java.util.Set[String]])
285+
configInstance = withLocalVariablesMethod.invoke(configInstance, localVariables)
286+
287+
val withErrorReporterMethod = configClass.getDeclaredMethod("withErrorReporter", classOf[java.util.function.Consumer[String]])
288+
configInstance = withErrorReporterMethod.invoke(configInstance, errorReporter)
243289

244-
method.invoke(instance, outDir, "CompiledExpression", classpath.mkString(java.io.File.pathSeparator), scalacOptions.toArray, source, line,
245-
expression, localVariableNames.asJava, packageName, consumer, false)
290+
configInstance
246291
}
247292

248293
private def getMetricsLogic(client: Client): Unit = {

scala/compiler-shared/src/org/jetbrains/plugins/scala/compiler/data/ExpressionEvaluationArguments.scala

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import org.jetbrains.jps.incremental.scala.Extractor
55
import java.nio.file.Path
66

77
case class ExpressionEvaluationArguments(
8+
useBuiltInExpressionCompiler: Boolean,
89
outDir: Path,
910
classpath: Seq[Path],
1011
scalacOptions: Seq[String],
@@ -18,6 +19,7 @@ case class ExpressionEvaluationArguments(
1819

1920
def asStrings: Seq[String] =
2021
Seq(
22+
useBuiltInExpressionCompiler.toString,
2123
pathToString(outDir),
2224
pathsToString(classpath),
2325
sequenceToString(scalacOptions),
@@ -34,6 +36,7 @@ object ExpressionEvaluationArguments {
3436

3537
def parse(strings: Seq[String]): Option[ExpressionEvaluationArguments] = strings match {
3638
case Seq(
39+
s2b(useBuiltInExpressionCompiler),
3740
StringToPath(outDir),
3841
StringToPaths(classpath),
3942
StringToSequence(scalacOptions),
@@ -43,10 +46,12 @@ object ExpressionEvaluationArguments {
4346
stringToSet(localVariableNames),
4447
packageName
4548
) =>
46-
Some(ExpressionEvaluationArguments(outDir, classpath, scalacOptions, source, line, expression, localVariableNames, packageName))
49+
Some(ExpressionEvaluationArguments(useBuiltInExpressionCompiler, outDir, classpath, scalacOptions, source, line, expression, localVariableNames, packageName))
4750
case _ => None
4851
}
4952

53+
private val s2b: Extractor[String, Boolean] = _.toBoolean
54+
5055
private val stringToSet: Extractor[String, Set[String]] = StringToSequence.andThen(_.toSet)(_)
5156

5257
private val s2i: Extractor[String, Int] = _.toInt

scala/debugger/src/org/jetbrains/plugins/scala/debugger/evaluation/ExpressionCompilerResolverListener.scala

+23-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import com.intellij.openapi.project.Project
66
import com.intellij.openapi.util.Key
77
import org.jetbrains.plugins.scala.DependencyManagerBase.RichStr
88
import org.jetbrains.plugins.scala.debugger.DebuggerBundle
9-
import org.jetbrains.plugins.scala.project.{ModuleExt, ProjectExt}
9+
import org.jetbrains.plugins.scala.project.{ModuleExt, ProjectExt, ScalaLanguageLevel}
1010
import org.jetbrains.plugins.scala.{DependencyManagerBase, ScalaVersion}
1111

1212
import java.nio.file.Path
@@ -29,13 +29,13 @@ private final class ExpressionCompilerResolverListener(project: Project) extends
2929
.flatMap(_.scalaMinorVersion)
3030
.filter(_.isScala3)
3131
.flatMap { v =>
32-
resolveExpressionCompilerJar(v, indicator) match {
33-
case Some(jar) => Some(v -> jar)
34-
case None => None
35-
}
32+
if (v.languageLevel >= ScalaLanguageLevel.Scala_3_7)
33+
Some(v -> ExpressionCompilerType.BuiltIn)
34+
else
35+
resolveExpressionCompilerJar(v, indicator).map(jar => v -> ExpressionCompilerType.ResolvedJar(jar))
3636
}.toMap
3737
} catch {
38-
case NonFatal(_) => Map.empty[ScalaVersion, Path]
38+
case NonFatal(_) => Map.empty[ScalaVersion, ExpressionCompilerType]
3939
}
4040

4141
project.putUserData(ExpressionCompilers, expressionCompilers)
@@ -53,7 +53,23 @@ private final class ExpressionCompilerResolverListener(project: Project) extends
5353
}
5454

5555
private object ExpressionCompilerResolverListener {
56-
final val ExpressionCompilers: Key[Map[ScalaVersion, Path]] = Key.create("scala_debugger_expression_compilers")
56+
57+
sealed trait ExpressionCompilerType
58+
object ExpressionCompilerType {
59+
/**
60+
* Scala 3.7 ships the debugger expression compiler as part of the scala3-compiler.jar. We do not need to manually
61+
* resolve a separate expression compiler jar.
62+
*/
63+
case object BuiltIn extends ExpressionCompilerType
64+
65+
/**
66+
* Scala 3.0 to Scala 3.6 use a separate jar which hosts the debugger expression compiler which needs to be
67+
* manually resolved.
68+
*/
69+
case class ResolvedJar(path: Path) extends ExpressionCompilerType
70+
}
71+
72+
final val ExpressionCompilers: Key[Map[ScalaVersion, ExpressionCompilerType]] = Key.create("scala_debugger_expression_compilers")
5773

5874
final val ScalaExpressionCompilerVersion = "4.2.4"
5975
}

scala/debugger/src/org/jetbrains/plugins/scala/debugger/evaluation/evaluator/ExpressionCompilerEvaluator.scala

+12-8
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,18 @@ private[evaluation] final class ExpressionCompilerEvaluator(codeFragment: PsiEle
4848
throw EvaluationException(DebuggerBundle.message("could.not.determine.scala.version", module.getName))
4949
}
5050

51-
val expressionCompilerJar = {
51+
val expressionCompilerType = {
5252
import ExpressionCompilerResolverListener.{ExpressionCompilers, ScalaExpressionCompilerVersion}
53-
context.getProject.getUserData(ExpressionCompilers).get(scalaVersion) match {
54-
case Some(jar) => jar
55-
case None =>
56-
throw EvaluationException(DebuggerBundle.message("could.not.resolve.scala.expression.compiler", ScalaExpressionCompilerVersion, scalaVersion.minor))
57-
}
53+
context.getProject.getUserData(ExpressionCompilers)
54+
.getOrElse(scalaVersion, throw EvaluationException(DebuggerBundle.message("could.not.resolve.scala.expression.compiler", ScalaExpressionCompilerVersion, scalaVersion.minor)))
55+
}
56+
57+
import ExpressionCompilerResolverListener.ExpressionCompilerType
58+
val expressionCompilerJar = expressionCompilerType match {
59+
case ExpressionCompilerType.BuiltIn => Seq.empty
60+
case ExpressionCompilerType.ResolvedJar(path) => Seq(path)
5861
}
62+
val useBuiltInExpressionCompiler = expressionCompilerType == ExpressionCompilerType.BuiltIn
5963

6064
try {
6165
def stripJarPathSuffix(path: String): String =
@@ -64,7 +68,7 @@ private[evaluation] final class ExpressionCompilerEvaluator(codeFragment: PsiEle
6468
val enumerator = OrderEnumerator.orderEntries(module).compileOnly().recursively()
6569
val classpath =
6670
module.scalaCompilerClasspath ++
67-
enumerator.getClassesRoots.map(_.getCanonicalPath).map(stripJarPathSuffix).map(Path.of(_)) :+
71+
enumerator.getClassesRoots.map(_.getCanonicalPath).map(stripJarPathSuffix).map(Path.of(_)) ++
6872
expressionCompilerJar
6973
val scalacOptions = module.scalaCompilerSettings.getOptionsAsStrings(module.hasScala3)
7074
val source = Path.of(position.getFile.getVirtualFile.getCanonicalPath)
@@ -81,7 +85,7 @@ private[evaluation] final class ExpressionCompilerEvaluator(codeFragment: PsiEle
8185
val thisObject = stackFrame.thisObject()
8286

8387
val packageName = inReadAction(ScalaPositionManager.findPackageName(position.getElementAt)).getOrElse("")
84-
val arguments = ExpressionEvaluationArguments(outDir, classpath, scalacOptions, source, line, expression, localVariableNames.toSet, packageName)
88+
val arguments = ExpressionEvaluationArguments(useBuiltInExpressionCompiler, outDir, classpath, scalacOptions, source, line, expression, localVariableNames.toSet, packageName)
8589

8690
val errors = Seq.newBuilder[NlsString]
8791
val client = new DummyClient() {

0 commit comments

Comments
 (0)