diff --git a/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelProcess.kt b/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelProcess.kt index da1eaffa5..2588a4fdd 100644 --- a/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelProcess.kt +++ b/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelProcess.kt @@ -1,32 +1,33 @@ package org.jetbrains.bsp.bazel.bazelrunner +import java.time.Duration import org.apache.logging.log4j.LogManager import org.jetbrains.bsp.bazel.bazelrunner.outputs.AsyncOutputProcessor import org.jetbrains.bsp.bazel.commons.Format import org.jetbrains.bsp.bazel.commons.Stopwatch import org.jetbrains.bsp.bazel.logger.BspClientLogger -import java.time.Duration class BazelProcess internal constructor( private val process: Process, - private val logger: BspClientLogger + private val logger: BspClientLogger, + private val originId: String? ) { - fun waitAndGetResult(): BazelProcessResult { - val outputProcessor = AsyncOutputProcessor(process, logger::message, LOGGER::info) - val stopwatch = Stopwatch.start() + fun waitAndGetResult(): BazelProcessResult { + val outputProcessor = AsyncOutputProcessor(process, { logger.message(it, originId) }, LOGGER::info) + val stopwatch = Stopwatch.start() - val exitCode = outputProcessor.waitForExit() - val duration = stopwatch.stop() - logCompletion(exitCode, duration) - return BazelProcessResult(outputProcessor.stdoutCollector, outputProcessor.stderrCollector, exitCode) - } + val exitCode = outputProcessor.waitForExit() + val duration = stopwatch.stop() + logCompletion(exitCode, duration) + return BazelProcessResult(outputProcessor.stdoutCollector, outputProcessor.stderrCollector, exitCode) + } - private fun logCompletion(exitCode: Int, duration: Duration) { - logger.message("Command completed in %s (exit code %d)", Format.duration(duration), exitCode) - } + private fun logCompletion(exitCode: Int, duration: Duration) { + logger.message("Command completed in %s (exit code %d)".format(Format.duration(duration), exitCode), originId) + } - companion object { - private val LOGGER = LogManager.getLogger(BazelProcess::class.java) - } + companion object { + private val LOGGER = LogManager.getLogger(BazelProcess::class.java) + } } diff --git a/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelRunner.kt b/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelRunner.kt index 7d9c3d20f..c43165e82 100644 --- a/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelRunner.kt +++ b/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelRunner.kt @@ -1,10 +1,10 @@ package org.jetbrains.bsp.bazel.bazelrunner +import java.nio.file.Path import org.apache.logging.log4j.LogManager import org.jetbrains.bsp.bazel.logger.BspClientLogger import org.jetbrains.bsp.bazel.workspacecontext.WorkspaceContext import org.jetbrains.bsp.bazel.workspacecontext.WorkspaceContextProvider -import java.nio.file.Path class BazelRunner private constructor( private val workspaceContextProvider: WorkspaceContextProvider, @@ -12,50 +12,60 @@ class BazelRunner private constructor( val workspaceRoot: Path?, ) { - companion object { - private val LOGGER = LogManager.getLogger(BazelRunner::class.java) + companion object { + private val LOGGER = LogManager.getLogger(BazelRunner::class.java) - @JvmStatic - fun of( - workspaceContextProvider: WorkspaceContextProvider, - bspClientLogger: BspClientLogger, - workspaceRoot: Path?, - ): BazelRunner { - return BazelRunner(workspaceContextProvider, bspClientLogger, workspaceRoot) + @JvmStatic + fun of( + workspaceContextProvider: WorkspaceContextProvider, + bspClientLogger: BspClientLogger, + workspaceRoot: Path?, + ): BazelRunner { + return BazelRunner(workspaceContextProvider, bspClientLogger, workspaceRoot) + } } - } - private var besBackendPort: Int? = null + private var besBackendPort: Int? = null - fun commandBuilder(): BazelRunnerCommandBuilder = BazelRunnerCommandBuilder(this) + fun commandBuilder(): BazelRunnerCommandBuilder = BazelRunnerCommandBuilder(this) - fun runBazelCommandBes(command: String, flags: List, arguments: List): BazelProcess { - fun besFlags() = listOf("--bes_backend=grpc://localhost:${besBackendPort!!}") + fun runBazelCommandBes( + command: String, + flags: List, + arguments: List, + originId: String? + ): BazelProcess { + fun besFlags() = listOf("--bes_backend=grpc://localhost:${besBackendPort!!}") - return runBazelCommand(command, flags = besFlags() + flags, arguments) - } + return runBazelCommand(command, flags = besFlags() + flags, arguments, originId) + } - fun runBazelCommand(command: String, flags: List, arguments: List): BazelProcess { - val workspaceContext = workspaceContextProvider.currentWorkspaceContext() + fun runBazelCommand( + command: String, + flags: List, + arguments: List, + originId: String? + ): BazelProcess { + val workspaceContext = workspaceContextProvider.currentWorkspaceContext() - val processArgs = listOf(bazel(workspaceContext), command) + buildFlags(workspaceContext) + flags + arguments - logInvocation(processArgs) - val processBuilder = ProcessBuilder(processArgs) - workspaceRoot?.let { processBuilder.directory(it.toFile()) } - val process = processBuilder.start() - return BazelProcess(process, bspClientLogger) - } + val processArgs = listOf(bazel(workspaceContext), command) + buildFlags(workspaceContext) + flags + arguments + logInvocation(processArgs, originId) + val processBuilder = ProcessBuilder(processArgs) + workspaceRoot?.let { processBuilder.directory(it.toFile()) } + val process = processBuilder.start() + return BazelProcess(process, bspClientLogger, originId) + } - private fun logInvocation(processArgs: List) { - "Invoking: ${processArgs.joinToString(" ")}" - .also { LOGGER.info(it) } - .also { bspClientLogger.message(it) } - } + private fun logInvocation(processArgs: List, originId: String?) { + "Invoking: ${processArgs.joinToString(" ")}" + .also { LOGGER.info(it) } + .also { bspClientLogger.message(it, originId) } + } - private fun bazel(workspaceContext: WorkspaceContext): String = workspaceContext.bazelPath.value.toString() - private fun buildFlags(workspaceContext: WorkspaceContext): List = workspaceContext.buildFlags.values + private fun bazel(workspaceContext: WorkspaceContext): String = workspaceContext.bazelPath.value.toString() + private fun buildFlags(workspaceContext: WorkspaceContext): List = workspaceContext.buildFlags.values - fun setBesBackendPort(port: Int) { - besBackendPort = port - } + fun setBesBackendPort(port: Int) { + besBackendPort = port + } } diff --git a/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelRunnerBuilder.kt b/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelRunnerBuilder.kt index 34a738fc0..501b5561e 100644 --- a/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelRunnerBuilder.kt +++ b/bazelrunner/src/main/java/org/jetbrains/bsp/bazel/bazelrunner/BazelRunnerBuilder.kt @@ -11,81 +11,82 @@ open class BazelRunnerBuilder internal constructor( private val bazelCommand: String ) { - private val flags = mutableListOf() - private val arguments = mutableListOf() - - fun withFlag(bazelFlag: String): BazelRunnerBuilder { - flags.add(bazelFlag) - return this - } - - fun withFlags(bazelFlags: List?): BazelRunnerBuilder { - flags.addAll(bazelFlags!!) - return this - } - - fun withArgument(bazelArgument: String): BazelRunnerBuilder { - arguments.add(bazelArgument) - return this - } - - fun withArguments(bazelArguments: List?): BazelRunnerBuilder { - arguments.addAll(bazelArguments!!) - return this - } - - open fun withTargets(bazelTargets: List): BazelRunnerBuilder { - val joinedTargets = BazelArgumentsUtils.getJoinedBazelTargets(bazelTargets) - arguments.add(joinedTargets) - return this - } - - open fun withTargets(targetsSpec: TargetsSpec): BazelRunnerBuilder { - val joinedTargets = BazelArgumentsUtils.joinBazelTargets(targetsSpec.values, targetsSpec.excludedValues) - arguments.add(joinedTargets) - return this - } - - open fun withTargets( - includedTargets: List, - excludedTargets: List - ): BazelRunnerBuilder? { - val joinedTargets = BazelArgumentsUtils.joinBazelTargets(includedTargets, excludedTargets) - arguments.add(joinedTargets) - return this - } - - fun withMnemonic(bazelTargets: List, languageIds: List): BazelRunnerBuilder { - val argument = BazelArgumentsUtils.getMnemonicWithJoinedTargets(bazelTargets, languageIds) - arguments.add(argument) - return this - } - - fun withKind(bazelParameter: BazelQueryKindParameters): BazelRunnerBuilder { - return withKinds(ImmutableList.of(bazelParameter)) - } - - fun withKinds(bazelParameters: List): BazelRunnerBuilder { - val argument = BazelArgumentsUtils.getQueryKindForPatternsAndExpressions(bazelParameters) - arguments.add(argument) - return this - } - - fun withKindsAndExcept( - parameters: BazelQueryKindParameters, - exception: String - ): BazelRunnerBuilder { - val argument = BazelArgumentsUtils.getQueryKindForPatternsAndExpressionsWithException( - listOf(parameters), exception) - arguments.add(argument) - return this - } - - fun executeBazelCommand(): BazelProcess { - return bazelRunner.runBazelCommand(bazelCommand, flags, arguments) - } - - fun executeBazelBesCommand(): BazelProcess { - return bazelRunner.runBazelCommandBes(bazelCommand, flags, arguments) - } + private val flags = mutableListOf() + private val arguments = mutableListOf() + + fun withFlag(bazelFlag: String): BazelRunnerBuilder { + flags.add(bazelFlag) + return this + } + + fun withFlags(bazelFlags: List?): BazelRunnerBuilder { + flags.addAll(bazelFlags!!) + return this + } + + fun withArgument(bazelArgument: String): BazelRunnerBuilder { + arguments.add(bazelArgument) + return this + } + + fun withArguments(bazelArguments: List?): BazelRunnerBuilder { + arguments.addAll(bazelArguments!!) + return this + } + + open fun withTargets(bazelTargets: List): BazelRunnerBuilder { + val joinedTargets = BazelArgumentsUtils.getJoinedBazelTargets(bazelTargets) + arguments.add(joinedTargets) + return this + } + + open fun withTargets(targetsSpec: TargetsSpec): BazelRunnerBuilder { + val joinedTargets = BazelArgumentsUtils.joinBazelTargets(targetsSpec.values, targetsSpec.excludedValues) + arguments.add(joinedTargets) + return this + } + + open fun withTargets( + includedTargets: List, + excludedTargets: List + ): BazelRunnerBuilder? { + val joinedTargets = BazelArgumentsUtils.joinBazelTargets(includedTargets, excludedTargets) + arguments.add(joinedTargets) + return this + } + + fun withMnemonic(bazelTargets: List, languageIds: List): BazelRunnerBuilder { + val argument = BazelArgumentsUtils.getMnemonicWithJoinedTargets(bazelTargets, languageIds) + arguments.add(argument) + return this + } + + fun withKind(bazelParameter: BazelQueryKindParameters): BazelRunnerBuilder { + return withKinds(ImmutableList.of(bazelParameter)) + } + + fun withKinds(bazelParameters: List): BazelRunnerBuilder { + val argument = BazelArgumentsUtils.getQueryKindForPatternsAndExpressions(bazelParameters) + arguments.add(argument) + return this + } + + fun withKindsAndExcept( + parameters: BazelQueryKindParameters, + exception: String + ): BazelRunnerBuilder { + val argument = BazelArgumentsUtils.getQueryKindForPatternsAndExpressionsWithException( + listOf(parameters), exception + ) + arguments.add(argument) + return this + } + + fun executeBazelCommand(): BazelProcess { + return bazelRunner.runBazelCommand(bazelCommand, flags, arguments, null) + } + + fun executeBazelBesCommand(originId: String?): BazelProcess { + return bazelRunner.runBazelCommandBes(bazelCommand, flags, arguments, originId) + } } diff --git a/logger/src/main/java/org/jetbrains/bsp/bazel/logger/BspClientLogger.java b/logger/src/main/java/org/jetbrains/bsp/bazel/logger/BspClientLogger.java index edd5b247e..1072d9c3c 100644 --- a/logger/src/main/java/org/jetbrains/bsp/bazel/logger/BspClientLogger.java +++ b/logger/src/main/java/org/jetbrains/bsp/bazel/logger/BspClientLogger.java @@ -13,16 +13,16 @@ public class BspClientLogger { private static final Duration LOG_OPERATION_THRESHOLD = Duration.ofMillis(100); private BuildClient bspClient; - public void error(String errorMessage) { - log(MessageType.ERROR, errorMessage); + public void error(String errorMessage, String originId) { + log(MessageType.ERROR, errorMessage, originId); } public void message(String format, Object... args) { - message(String.format(format, args)); + log(MessageType.LOG, String.format(format, args), null); } - public void message(String message) { - log(MessageType.LOG, message); + public void message(String message, String originId) { + log(MessageType.LOG, message, originId); } public void warn(String format, Object... args) { @@ -30,31 +30,34 @@ public void warn(String format, Object... args) { } public void warn(String message) { - log(MessageType.WARNING, message); + log(MessageType.WARNING, message, null); } - private void log(MessageType messageType, String message) { + private void log(MessageType messageType, String message, String originId) { if (bspClient == null) return; if (!message.trim().isEmpty()) { var params = new LogMessageParams(messageType, message); + params.setOriginId(originId); bspClient.onBuildLogMessage(params); } } - public T timed(String description, Supplier supplier) { + public T timed(String description, String originId, Supplier supplier) { var sw = Stopwatch.start(); T result = supplier.get(); var duration = sw.stop(); if (duration.compareTo(LOG_OPERATION_THRESHOLD) >= 0) { - message("%s completed in %s", description, Format.duration(duration)); + message( + String.format("%s completed in %s", description, Format.duration(duration)), originId); } return result; } - public void timed(String description, Runnable runnable) { + public void timed(String description, String originId, Runnable runnable) { timed( description, + originId, () -> { runnable.run(); return null; diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/bloop/BloopExporter.java b/server/src/main/java/org/jetbrains/bsp/bazel/server/bloop/BloopExporter.java index e8537489d..9a90dbb6b 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/bloop/BloopExporter.java +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/bloop/BloopExporter.java @@ -74,6 +74,7 @@ public void export() throws BazelExportFailedException { .getBspClientLogger() .timed( "Exporting to bloop", + null, () -> { var bloopPath = bspInfo.bspProjectRoot().resolve(".bloop"); var writtenFiles = new BspProjectExporter(project, bloopPath).export(); @@ -163,11 +164,11 @@ public void onBuildTargetDidChange(DidChangeBuildTarget didChangeBuildTarget) {} private static final class NoopProjectStorage implements ProjectStorage { @Override - public Project load() { + public Project load(String originId) { return null; } @Override - public void store(Project project) {} + public void store(Project project, String originId) {} } } diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspAspectsManager.java b/server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspAspectsManager.java index de1fe6e0a..b93d3a0bd 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspAspectsManager.java +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspAspectsManager.java @@ -21,7 +21,7 @@ public BazelBspAspectsManager( } public BepOutput fetchFilesFromOutputGroups( - TargetsSpec targetSpecs, String aspect, List outputGroups) { + TargetsSpec targetSpecs, String aspect, List outputGroups, String originId) { var result = bazelBspCompilationManager.buildTargetsWithBep( targetSpecs, @@ -32,7 +32,8 @@ public BepOutput fetchFilesFromOutputGroups( BazelFlag.outputGroups(outputGroups), BazelFlag.keepGoing(), BazelFlag.color(true), - BazelFlag.buildManualTests())); + BazelFlag.buildManualTests()), + originId); return result.bepOutput(); } } diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspCompilationManager.java b/server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspCompilationManager.java index f84a0d847..2b08e10c2 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspCompilationManager.java +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/managers/BazelBspCompilationManager.java @@ -1,6 +1,5 @@ package org.jetbrains.bsp.bazel.server.bsp.managers; -import io.vavr.collection.List; import io.vavr.collection.Seq; import org.jetbrains.bsp.bazel.bazelrunner.BazelRunner; import org.jetbrains.bsp.bazel.server.bep.BepServer; @@ -15,18 +14,15 @@ public BazelBspCompilationManager(BazelRunner bazelRunner) { this.bazelRunner = bazelRunner; } - public BepBuildResult buildTargetsWithBep(TargetsSpec targetSpecs) { - return buildTargetsWithBep(targetSpecs, List.empty()); - } - - public BepBuildResult buildTargetsWithBep(TargetsSpec targetSpecs, Seq extraFlags) { + public BepBuildResult buildTargetsWithBep( + TargetsSpec targetSpecs, Seq extraFlags, String originId) { var result = bazelRunner .commandBuilder() .build() .withFlags(extraFlags.asJava()) .withTargets(targetSpecs) - .executeBazelBesCommand() + .executeBazelBesCommand(originId) .waitAndGetResult(); return new BepBuildResult(result, bepServer.getBepOutput()); } diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ExecuteService.kt b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ExecuteService.kt index bd6676230..86148a835 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ExecuteService.kt +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ExecuteService.kt @@ -14,6 +14,7 @@ import org.eclipse.lsp4j.jsonrpc.messages.ResponseError import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode import org.jetbrains.bsp.bazel.bazelrunner.BazelProcessResult import org.jetbrains.bsp.bazel.bazelrunner.BazelRunner +import org.jetbrains.bsp.bazel.bazelrunner.params.BazelFlag import org.jetbrains.bsp.bazel.server.bsp.managers.BazelBspCompilationManager import org.jetbrains.bsp.bazel.server.sync.BspMappings.toBspId import org.jetbrains.bsp.bazel.server.sync.model.Module @@ -28,25 +29,25 @@ class ExecuteService( private val workspaceContextProvider: WorkspaceContextProvider ) { fun compile(params: CompileParams): CompileResult { - val targets = selectTargets(params.targets) - val result = build(targets) - return CompileResult(result.statusCode) + val targets = selectTargets(params.targets, params.originId) + val result = build(targets, params.originId) + return CompileResult(result.statusCode).apply { originId = params.originId } } fun test(params: TestParams): TestResult { - val targets = selectTargets(params.targets) - var result = build(targets) + val targets = selectTargets(params.targets, params.originId) + var result = build(targets, params.originId) if (result.isNotSuccess) { return TestResult(result.statusCode) } result = bazelRunner.commandBuilder().test().withTargets( targets.map(BspMappings::toBspUri) - ).withArguments(params.arguments).executeBazelBesCommand().waitAndGetResult() - return TestResult(result.statusCode) + ).withArguments(params.arguments).executeBazelBesCommand(params.originId).waitAndGetResult() + return TestResult(result.statusCode).apply { originId = originId } } fun run(params: RunParams): RunResult { - val targets = selectTargets(listOf(params.target)) + val targets = selectTargets(listOf(params.target), params.originId) if (targets.isEmpty()) { throw ResponseErrorException( ResponseError( @@ -57,29 +58,33 @@ class ExecuteService( ) } val bspId = targets.single() - val result = build(targets) + val result = build(targets, params.originId) if (result.isNotSuccess) { return RunResult(result.statusCode) } val bazelProcessResult = bazelRunner.commandBuilder().run().withArgument(BspMappings.toBspUri(bspId)) - .withArguments(params.arguments).executeBazelBesCommand().waitAndGetResult() - return RunResult(bazelProcessResult.statusCode) + .withArguments(params.arguments).executeBazelBesCommand(params.originId).waitAndGetResult() + return RunResult(bazelProcessResult.statusCode).apply { originId = originId } } fun clean(params: CleanCacheParams?): CleanCacheResult { val bazelResult = - bazelRunner.commandBuilder().clean().executeBazelBesCommand().waitAndGetResult() + bazelRunner.commandBuilder().clean().executeBazelBesCommand(null).waitAndGetResult() return CleanCacheResult(bazelResult.stdout, true) } - private fun build(bspIds: List): BazelProcessResult { + private fun build(bspIds: List, originId: String): BazelProcessResult { val targetsSpec = TargetsSpec(bspIds, emptyList()) - return compilationManager.buildTargetsWithBep(targetsSpec).processResult() + return compilationManager.buildTargetsWithBep( + targetsSpec, + io.vavr.collection.Array.of(BazelFlag.color(true)), + originId + ).processResult() } - private fun selectTargets(targets: List): List { - val project = projectProvider.get() + private fun selectTargets(targets: List, originId: String): List { + val project = projectProvider.get(originId) val modules: Set = BspMappings.getModules(project, targets) val modulesToBuild = modules.filter { m: Module -> isBuildable(m) } return modulesToBuild.map(::toBspId) diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/FileProjectStorage.kt b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/FileProjectStorage.kt index 78ba0fe7f..6161dbe0b 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/FileProjectStorage.kt +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/FileProjectStorage.kt @@ -1,12 +1,12 @@ package org.jetbrains.bsp.bazel.server.sync import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import org.jetbrains.bsp.bazel.logger.BspClientLogger -import org.jetbrains.bsp.bazel.server.bsp.info.BspInfo -import org.jetbrains.bsp.bazel.server.sync.model.Project import java.io.IOException import java.nio.file.Files import java.nio.file.Path +import org.jetbrains.bsp.bazel.logger.BspClientLogger +import org.jetbrains.bsp.bazel.server.bsp.info.BspInfo +import org.jetbrains.bsp.bazel.server.sync.model.Project class FileProjectStorage(private val path: Path, private val logger: BspClientLogger) : ProjectStorage { @@ -17,27 +17,27 @@ class FileProjectStorage(private val path: Path, private val logger: BspClientLo bspInfo.bazelBspDir().resolve("project-cache.json"), logger ) - override fun load(): Project? = path.takeIf(Files::exists)?.let { read() } + override fun load(originId: String?): Project? = path.takeIf(Files::exists)?.let { read(originId) } - private fun read(): Project = logger.timed( - "Loading project from local cache" + private fun read(originId: String?): Project = logger.timed( + "Loading project from local cache", originId ) { try { return@timed mapper.readValue(path.toFile(), Project::class.java) } catch (e: IOException) { // TODO figure out why this error is otherwise not propagated to bsp client - logger.error(e.toString()) + logger.error(e.toString(), originId) throw RuntimeException(e) } } - override fun store(project: Project) = logger.timed( - "Saving project to local cache" + override fun store(project: Project, originId: String?) = logger.timed( + "Saving project to local cache", originId ) { try { mapper.writeValue(path.toFile(), project) } catch (e: IOException) { - logger.error(e.toString()) + logger.error(e.toString(), originId) throw RuntimeException(e) } } diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectProvider.kt b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectProvider.kt index 6cf20ac96..ea1d1955c 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectProvider.kt +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectProvider.kt @@ -9,19 +9,22 @@ class ProjectProvider( @Synchronized fun refreshAndGet(): Project = - loadFromBazel() + loadFromBazel(null) @Synchronized - fun get(): Project = project ?: loadFromDisk() ?: loadFromBazel() + fun get(): Project = project ?: loadFromDisk(null) ?: loadFromBazel(null) - private fun loadFromBazel() = projectResolver.resolve().also { + @Synchronized + fun get(originId: String?): Project = project ?: loadFromDisk(originId) ?: loadFromBazel(originId) + + private fun loadFromBazel(originId: String?) = projectResolver.resolve(originId).also { project = it - storeOnDisk() + storeOnDisk(originId) } - private fun loadFromDisk() = projectStorage.load()?.also { + private fun loadFromDisk(originId: String?) = projectStorage.load(originId)?.also { project = it } - private fun storeOnDisk() = projectStorage.store(project) + private fun storeOnDisk(originId: String?) = projectStorage.store(project, originId) } diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectResolver.kt b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectResolver.kt index 15019a258..6426f259e 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectResolver.kt +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectResolver.kt @@ -1,5 +1,6 @@ package org.jetbrains.bsp.bazel.server.sync +import java.net.URI import org.jetbrains.bsp.bazel.info.BspTargetInfo.TargetInfo import org.jetbrains.bsp.bazel.logger.BspClientLogger import org.jetbrains.bsp.bazel.server.bep.BepOutput @@ -7,7 +8,6 @@ import org.jetbrains.bsp.bazel.server.bsp.managers.BazelBspAspectsManager import org.jetbrains.bsp.bazel.server.sync.model.Project import org.jetbrains.bsp.bazel.workspacecontext.WorkspaceContext import org.jetbrains.bsp.bazel.workspacecontext.WorkspaceContextProvider -import java.net.URI /** Responsible for querying bazel and constructing Project instance */ class ProjectResolver( @@ -17,31 +17,33 @@ class ProjectResolver( private val logger: BspClientLogger, private val targetInfoReader: TargetInfoReader ) { - fun resolve(): Project { + fun resolve(originId: String?): Project { val workspaceContext = logger.timed( "Reading project view and creating workspace context", + originId, workspaceContextProvider::currentWorkspaceContext ) val bepOutput = logger.timed( - "Building project with aspect" - ) { buildProjectWithAspect(workspaceContext) } + "Building project with aspect", originId + ) { buildProjectWithAspect(workspaceContext, originId) } val aspectOutputs = logger.timed>( - "Reading aspect output paths" + "Reading aspect output paths", originId ) { bepOutput.filesByOutputGroupNameTransitive(BSP_INFO_OUTPUT_GROUP) } val rootTargets = bepOutput.rootTargets() val targets = logger.timed>( - "Parsing aspect outputs" + "Parsing aspect outputs", originId ) { targetInfoReader.readTargetMapFromAspectOutputs(aspectOutputs) } return logger.timed( - "Mapping to internal model" + "Mapping to internal model", originId ) { bazelProjectMapper.createProject(targets, rootTargets, workspaceContext) } } - private fun buildProjectWithAspect(workspaceContext: WorkspaceContext): BepOutput = + private fun buildProjectWithAspect(workspaceContext: WorkspaceContext, originId: String?): BepOutput = bazelBspAspectsManager.fetchFilesFromOutputGroups( workspaceContext.targets, ASPECT_NAME, - listOf(BSP_INFO_OUTPUT_GROUP, ARTIFACTS_OUTPUT_GROUP) + listOf(BSP_INFO_OUTPUT_GROUP, ARTIFACTS_OUTPUT_GROUP), + originId ) diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectStorage.java b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectStorage.java index 933120790..f35495436 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectStorage.java +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectStorage.java @@ -3,7 +3,7 @@ import org.jetbrains.bsp.bazel.server.sync.model.Project; public interface ProjectStorage { - Project load(); + Project load(String originId); - void store(Project project); + void store(Project project, String originId); } diff --git a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectSyncService.java b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectSyncService.java index c97a94b27..39a7db932 100644 --- a/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectSyncService.java +++ b/server/src/main/java/org/jetbrains/bsp/bazel/server/sync/ProjectSyncService.java @@ -103,12 +103,12 @@ public ScalacOptionsResult buildTargetScalacOptions(ScalacOptionsParams params) } public ScalaTestClassesResult buildTargetScalaTestClasses(ScalaTestClassesParams params) { - var project = projectProvider.get(); + var project = projectProvider.get(params.getOriginId()); return bspMapper.buildTargetScalaTestClasses(project, params); } public ScalaMainClassesResult buildTargetScalaMainClasses(ScalaMainClassesParams params) { - var project = projectProvider.get(); + var project = projectProvider.get(params.getOriginId()); return bspMapper.buildTargetScalaMainClasses(project, params); } diff --git a/server/src/test/java/org/jetbrains/bsp/bazel/server/sync/ProjectStorageTest.kt b/server/src/test/java/org/jetbrains/bsp/bazel/server/sync/ProjectStorageTest.kt index f50d3a747..304addb81 100644 --- a/server/src/test/java/org/jetbrains/bsp/bazel/server/sync/ProjectStorageTest.kt +++ b/server/src/test/java/org/jetbrains/bsp/bazel/server/sync/ProjectStorageTest.kt @@ -1,6 +1,9 @@ package org.jetbrains.bsp.bazel.server.sync import io.kotest.matchers.shouldBe +import java.io.IOException +import java.net.URI +import java.nio.file.Files import org.jetbrains.bsp.bazel.logger.BspClientLogger import org.jetbrains.bsp.bazel.server.sync.languages.java.JavaModule import org.jetbrains.bsp.bazel.server.sync.languages.java.Jdk @@ -14,9 +17,6 @@ import org.jetbrains.bsp.bazel.server.sync.model.SourceSet import org.jetbrains.bsp.bazel.server.sync.model.Tag import org.jetbrains.bsp.bazel.utils.dope.DopeTemp.createTempPath import org.junit.jupiter.api.Test -import java.io.IOException -import java.net.URI -import java.nio.file.Files class ProjectStorageTest { @Test @@ -25,7 +25,7 @@ class ProjectStorageTest { val path = createTempPath("project-cache-test.json") Files.deleteIfExists(path) val storage = FileProjectStorage(path, BspClientLogger()) - val empty = storage.load() + val empty = storage.load(null) empty shouldBe null val scalaModule = ScalaModule( ScalaSdk("org.scala", "2.12.3", "2.12", emptyList()), emptyList(), JavaModule( @@ -44,7 +44,8 @@ class ProjectStorageTest { ) ) val project = Project( - URI.create("file:///root"), listOf( + URI.create("file:///root"), + listOf( Module( Label("//project:project"), false, @@ -61,10 +62,11 @@ class ProjectStorageTest { scalaModule, hashMapOf() ) - ), mapOf(URI.create("file:///root/project/Lib.java") to Label("file:///root")), + ), + mapOf(URI.create("file:///root/project/Lib.java") to Label("file:///root")), ) - storage.store(project) - val loaded = storage.load() + storage.store(project, null) + val loaded = storage.load(null) loaded shouldBe project } }