Skip to content

Commit

Permalink
[fix] Read classpath on demand in javacOptions and scalacOptions requ…
Browse files Browse the repository at this point in the history
…ests handlers

Co-authored-by: Tomasz Pasternak <Tomasz.Pasternak@jetbrains.com>


Merge-request: BAZEL-MR-664
Merged-by: Marcin Abramowicz <marcin.abramowicz@jetbrains.com>
  • Loading branch information
tpasternak authored and Space Team committed Nov 24, 2023
1 parent e38dd11 commit a10ecb0
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 53 deletions.
4 changes: 0 additions & 4 deletions aspects/rules/jvm/jvm_info.bzl
Expand Up @@ -136,9 +136,7 @@ def extract_jvm_info(target, ctx, output_groups, **kwargs):
resolve_files += compile_jars
resolve_files += source_jars

runtime_classpath = map(file_location, runtime_jars)
compile_classpath = map(file_location, compile_jars)
source_classpath = map(file_location, source_jars)

javac_opts = getattr(ctx.rule.attr, "javacopts", [])
jvm_flags = getattr(ctx.rule.attr, "jvm_flags", [])
Expand All @@ -151,9 +149,7 @@ def extract_jvm_info(target, ctx, output_groups, **kwargs):
info = create_struct(
jars = jars,
generated_jars = generated_jars,
runtime_classpath = runtime_classpath,
compile_classpath = compile_classpath,
source_classpath = source_classpath,
javac_opts = javac_opts,
jvm_flags = jvm_flags,
main_class = main_class,
Expand Down
Expand Up @@ -38,6 +38,7 @@ import ch.epfl.scala.bsp4j.ScalaMainClassesParams
import ch.epfl.scala.bsp4j.ScalaMainClassesResult
import ch.epfl.scala.bsp4j.ScalaTestClassesParams
import ch.epfl.scala.bsp4j.ScalaTestClassesResult
import ch.epfl.scala.bsp4j.ScalacOptionsItem
import ch.epfl.scala.bsp4j.ScalacOptionsParams
import ch.epfl.scala.bsp4j.ScalacOptionsResult
import ch.epfl.scala.bsp4j.SourceItem
Expand All @@ -58,7 +59,10 @@ import org.jetbrains.bsp.bazel.bazelrunner.BazelRunner
import org.jetbrains.bsp.bazel.commons.Constants
import org.jetbrains.bsp.bazel.server.bsp.info.BspInfo
import org.jetbrains.bsp.bazel.server.sync.languages.LanguagePluginsService
import org.jetbrains.bsp.bazel.server.sync.languages.java.IdeClasspathResolver
import org.jetbrains.bsp.bazel.server.sync.languages.java.JavaModule
import org.jetbrains.bsp.bazel.server.sync.languages.jvm.javaModule
import org.jetbrains.bsp.bazel.server.sync.languages.scala.ScalaModule
import org.jetbrains.bsp.bazel.server.sync.model.Label
import org.jetbrains.bsp.bazel.server.sync.model.Language
import org.jetbrains.bsp.bazel.server.sync.model.Module
Expand Down Expand Up @@ -322,14 +326,34 @@ class BspProjectMapper(
.filter { it.toFile().exists() } // I'm surprised this is needed, but we literally test it in e2e tests
.map { it.toUri() }

fun buildTargetJavacOptions(project: Project, params: JavacOptionsParams): JavacOptionsResult {
fun extractJavacOptionsItem(module: Module): JavacOptionsItem? =
module.javaModule?.let {
languagePluginsService.javaLanguagePlugin.toJavacOptionsItem(module, it)
private fun toJavacOptionsItem(module: Module, javaModule: JavaModule, ideClasspath: List<URI>): JavacOptionsItem =
JavacOptionsItem(
BspMappings.toBspId(module),
javaModule.javacOpts.toList(),
ideClasspath.map { it.toString() }.toList(),
javaModule.mainOutput.toString()
)
private fun toScalacOptionsItem(module: Module, ideClasspath: List<URI>): ScalacOptionsItem? =
(module.languageData as? ScalaModule)?.let {scalaModule ->
return scalaModule.javaModule?.let {javaModule ->
val javacOptions = toJavacOptionsItem(module, javaModule, ideClasspath)
return ScalacOptionsItem(
javacOptions.target,
scalaModule.scalacOpts,
javacOptions.classpath,
javacOptions.classDirectory
)
}
}

val modules = BspMappings.getModules(project, params.targets)
val items = modules.mapNotNull(::extractJavacOptionsItem)
fun buildTargetJavacOptions(project: Project, params: JavacOptionsParams, cancelChecker: CancelChecker): JavacOptionsResult {
val items = params.targets.map { targetIdentifier ->
val label = Label(targetIdentifier.uri)
val module = project.findModule(label)
?: return@map null // This is a silent failure, equivalent of .mapNotNull used previously
val ideClasspath = readIdeClasspath(targetIdentifier, cancelChecker)
module.javaModule?.let { toJavacOptionsItem(module, it, ideClasspath) }
}.filterNotNull()
return JavacOptionsResult(items)
}

Expand All @@ -356,18 +380,31 @@ class BspProjectMapper(
languagePluginsService.pythonLanguagePlugin.toPythonOptionsItem(module, it)
}


fun buildTargetScalacOptions(
project: Project,
params: ScalacOptionsParams
project: Project,
params: ScalacOptionsParams,
cancelChecker: CancelChecker
): ScalacOptionsResult {
val labels = params.targets.map(BuildTargetIdentifier::getUri).map(::Label)
val modules = labels.mapNotNull(project::findModule)
val scalaLanguagePlugin = languagePluginsService.scalaLanguagePlugin
val items = modules.mapNotNull(scalaLanguagePlugin::toScalacOptionsItem)
val items = params.targets.map { targetIdentifier ->
val label = Label(targetIdentifier.uri)
val module = project.findModule(label) ?: return@map null // This is a silent failure, equivalent of .mapNotNull used previously
val ideClasspath = readIdeClasspath(targetIdentifier, cancelChecker)
toScalacOptionsItem(module, ideClasspath)
}.filterNotNull()
return ScalacOptionsResult(items)
}

private fun readIdeClasspath(targetIdentifier: BuildTargetIdentifier, cancelChecker: CancelChecker): List<URI> {
val label = Label(targetIdentifier.uri)
val classPathFromQuery = ClasspathQuery.classPathQuery(targetIdentifier, cancelChecker, bspInfo, bazelRunner)
val ideClasspath = IdeClasspathResolver.resolveIdeClasspath(
label = label,
bazelPathsResolver = bazelPathsResolver,
runtimeClasspath = resolveClasspath(classPathFromQuery.runtime_classpath),
compileClasspath = resolveClasspath(classPathFromQuery.compile_classpath))
return ideClasspath
}

fun buildTargetScalaTestClasses(
project: Project, params: ScalaTestClassesParams
): ScalaTestClassesResult {
Expand Down
Expand Up @@ -113,7 +113,7 @@ class ProjectSyncService(private val bspMapper: BspProjectMapper, private val pr

fun buildTargetJavacOptions(cancelChecker: CancelChecker, params: JavacOptionsParams): JavacOptionsResult {
val project = projectProvider.get(cancelChecker)
return bspMapper.buildTargetJavacOptions(project, params)
return bspMapper.buildTargetJavacOptions(project, params, cancelChecker)
}

fun buildTargetCppOptions(cancelChecker: CancelChecker, params: CppOptionsParams): CppOptionsResult {
Expand All @@ -128,7 +128,7 @@ class ProjectSyncService(private val bspMapper: BspProjectMapper, private val pr

fun buildTargetScalacOptions(cancelChecker: CancelChecker, params: ScalacOptionsParams): ScalacOptionsResult {
val project = projectProvider.get(cancelChecker)
return bspMapper.buildTargetScalacOptions(project, params)
return bspMapper.buildTargetScalacOptions(project, params, cancelChecker)
}

fun buildTargetScalaTestClasses(
Expand Down
Expand Up @@ -62,5 +62,15 @@ class IdeClasspathResolver(

companion object {
private val JAR_PATTERN = ("((-[hi]jar)|(\\.abi))\\.jar\$").toRegex()

fun resolveIdeClasspath(label: Label,
bazelPathsResolver: BazelPathsResolver,
runtimeClasspath: List<URI>,
compileClasspath: List<URI>) =
IdeClasspathResolver(
label,
bazelPathsResolver,
runtimeClasspath.asSequence(),
compileClasspath.asSequence()).resolve().toList()
}
}
Expand Up @@ -39,13 +39,7 @@ class JavaLanguagePlugin(
it.interfaceJarsList + it.binaryJarsList
}.map(bazelPathsResolver::resolveUri)
val mainClass = getMainClass(this)
val runtimeClasspath = bazelPathsResolver.resolveUris(runtimeClasspathList, true)
val compileClasspath = bazelPathsResolver.resolveUris(compileClasspathList + generatedJarsList.flatMap { it.binaryJarsList }, true)
val sourcesClasspath = bazelPathsResolver.resolveUris(sourceClasspathList, true)
val ideClasspath = resolveIdeClasspath(Label(targetInfo.id),
bazelPathsResolver,
runtimeClasspath.asSequence(), compileClasspath.asSequence()
)
val runtimeJdk = jdkResolver.resolveJdk(targetInfo)

JavaModule(
Expand All @@ -57,9 +51,7 @@ class JavaLanguagePlugin(
allOutputs,
mainClass,
argsList,
compileClasspath,
sourcesClasspath,
ideClasspath
compileClasspath
)
}

Expand Down Expand Up @@ -111,11 +103,4 @@ class JavaLanguagePlugin(
}
}

fun toJavacOptionsItem(module: Module, javaModule: JavaModule): JavacOptionsItem =
JavacOptionsItem(
BspMappings.toBspId(module),
javaModule.javacOpts.toList(),
javaModule.ideClasspath.map { it.toString() }.toList(),
javaModule.mainOutput.toString()
)
}
Expand Up @@ -19,6 +19,4 @@ data class JavaModule(
val mainClass: String?,
val args: List<String>,
val compileClasspath: List<URI>,
val sourcesClasspath: List<URI>,
val ideClasspath: List<URI>
) : LanguageData
Expand Up @@ -7,7 +7,6 @@ import ch.epfl.scala.bsp4j.ScalaMainClass
import ch.epfl.scala.bsp4j.ScalaMainClassesItem
import ch.epfl.scala.bsp4j.ScalaPlatform
import ch.epfl.scala.bsp4j.ScalaTestClassesItem
import ch.epfl.scala.bsp4j.ScalacOptionsItem
import org.jetbrains.bsp.bazel.info.BspTargetInfo
import org.jetbrains.bsp.bazel.server.sync.BazelPathsResolver
import org.jetbrains.bsp.bazel.server.sync.BspMappings
Expand Down Expand Up @@ -73,17 +72,6 @@ class ScalaLanguagePlugin(
return JVMLanguagePluginParser.calculateJVMSourceRoot(source, true)
}

fun toScalacOptionsItem(module: Module): ScalacOptionsItem? =
withScalaAndJavaModules(module) { scalaModule: ScalaModule, javaModule: JavaModule ->
val javacOptions = javaLanguagePlugin.toJavacOptionsItem(module, javaModule)
ScalacOptionsItem(
javacOptions.target,
scalaModule.scalacOpts,
javacOptions.classpath,
javacOptions.classDirectory
)
}

fun toScalaTestClassesItem(module: Module): ScalaTestClassesItem? =
if (!module.tags.contains(Tag.TEST) || !module.languages
.contains(Language.SCALA)
Expand Down
Expand Up @@ -30,9 +30,7 @@ message JvmOutputs {
message JvmTargetInfo {
repeated JvmOutputs jars = 1;
repeated JvmOutputs generated_jars = 2;
repeated FileLocation runtime_classpath = 3;
repeated FileLocation compile_classpath = 4;
repeated FileLocation source_classpath = 5;
repeated string javac_opts = 6;
repeated string jvm_flags = 7;
string main_class = 8;
Expand Down
Expand Up @@ -39,8 +39,6 @@ class ProjectStorageTest {
null,
emptyList(),
emptyList(),
emptyList(),
emptyList()
)
)
val project = Project(
Expand Down

0 comments on commit a10ecb0

Please sign in to comment.