Skip to content
This repository was archived by the owner on Aug 5, 2024. It is now read-only.

Commit 26ef246

Browse files
Tomasz PasternakSpace Team
authored andcommitted
Inverse sources with query
refactor throw -> error fixup! Typo fix fixup! Typo fix Typo fix Tiny cleanup Fix unit tests [fix] Support bazel 5 in inverse sources query WIP Inverse sources with query Co-authored-by: Xuan Son Trinh <[email protected]> Merge-request: BAZEL-MR-771 Merged-by: Tomasz Pasternak <[email protected]>
1 parent a2f623b commit 26ef246

File tree

7 files changed

+86
-9
lines changed

7 files changed

+86
-9
lines changed

server/src/main/kotlin/org/jetbrains/bsp/bazel/server/sync/BazelProjectMapper.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ class BazelProjectMapper(
4848
targets: Map<String, TargetInfo>,
4949
rootTargets: Set<String>,
5050
allTargetNames: List<String>,
51-
workspaceContext: WorkspaceContext
51+
workspaceContext: WorkspaceContext,
52+
bazelInfo: BazelInfo
5253
): Project {
5354
languagePluginsService.prepareSync(targets.values.asSequence())
5455
val dependencyTree = measure("Build dependency tree") {
@@ -106,7 +107,7 @@ class BazelProjectMapper(
106107
createRustExternalModules(rustExternalTargetsToImport, dependencyTree, librariesFromDeps)
107108
}
108109
val allModules = modulesFromBazel + rustExternalModules
109-
return Project(workspaceRoot, allModules.toList(), sourceToTarget, librariesToImport, invalidTargets)
110+
return Project(workspaceRoot, allModules.toList(), sourceToTarget, librariesToImport, invalidTargets, bazelInfo.release)
110111
}
111112

112113
private fun <K, V> concatenateMaps(vararg maps: Map<K, List<V>>): Map<K, List<V>> =

server/src/main/kotlin/org/jetbrains/bsp/bazel/server/sync/BspProjectMapper.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import java.net.URI
7575
import java.nio.file.Path
7676
import java.nio.file.Paths
7777
import kotlin.io.path.name
78+
import kotlin.io.path.relativeToOrNull
7879
import kotlin.io.path.toPath
7980

8081
class BspProjectMapper(
@@ -243,13 +244,13 @@ class BspProjectMapper(
243244
}
244245

245246
fun inverseSources(
246-
project: Project, inverseSourcesParams: InverseSourcesParams
247+
project: Project, inverseSourcesParams: InverseSourcesParams, cancelChecker: CancelChecker
247248
): InverseSourcesResult {
248249
val documentUri = BspMappings.toUri(inverseSourcesParams.textDocument)
249-
val targets = project.findTargetBySource(documentUri)
250-
?.let { listOf(BspMappings.toBspId(it)) }
251-
.orEmpty()
252-
return InverseSourcesResult(targets)
250+
val documentRelativePath = documentUri
251+
.toPath()
252+
.relativeToOrNull(project.workspaceRoot.toPath()) ?: throw RuntimeException("File path outside of project root")
253+
return InverseSourcesQuery.inverseSourcesQuery(documentRelativePath, bazelRunner, project.bazelRelease, cancelChecker)
253254
}
254255

255256
fun dependencySources(
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.jetbrains.bsp.bazel.server.sync
2+
3+
import ch.epfl.scala.bsp4j.BuildTargetIdentifier
4+
import ch.epfl.scala.bsp4j.InverseSourcesResult
5+
import ch.epfl.scala.bsp4j.StatusCode
6+
import org.eclipse.lsp4j.jsonrpc.CancelChecker
7+
import org.jetbrains.bsp.bazel.bazelrunner.BazelRelease
8+
import org.jetbrains.bsp.bazel.bazelrunner.BazelRunner
9+
import java.nio.file.Path
10+
11+
object InverseSourcesQuery {
12+
fun inverseSourcesQuery(
13+
documentRelativePath: Path,
14+
bazelRunner: BazelRunner,
15+
bazelInfo: BazelRelease,
16+
cancelChecker: CancelChecker
17+
): InverseSourcesResult {
18+
val fileLabel = fileLabel(documentRelativePath, bazelRunner, cancelChecker)
19+
?: return InverseSourcesResult(
20+
emptyList()
21+
)
22+
val listOfLabels = targetLabels(fileLabel, bazelRunner, bazelInfo, cancelChecker)
23+
return InverseSourcesResult(listOfLabels.map { BuildTargetIdentifier(it) })
24+
}
25+
26+
/**
27+
* @return list of targets that contain `fileLabel` in their `srcs` attribute
28+
*/
29+
private fun targetLabels(
30+
fileLabel: String,
31+
bazelRunner: BazelRunner,
32+
bazelRelease: BazelRelease,
33+
cancelChecker: CancelChecker
34+
): List<String> {
35+
val packageLabel = fileLabel.replace(":.*".toRegex(), ":*")
36+
val consistentLabelsArg = listOfNotNull(if (bazelRelease.major >= 6) "--consistent_labels" else null) // #bazel5
37+
val targetLabelsQuery =
38+
bazelRunner.commandBuilder().query()
39+
.withArgument("attr('srcs', ${fileLabel}, ${packageLabel})")
40+
.withArguments(consistentLabelsArg)
41+
.executeBazelCommand(null).waitAndGetResult(cancelChecker)
42+
if (targetLabelsQuery.statusCode == StatusCode.OK) {
43+
return targetLabelsQuery.stdoutLines
44+
} else {
45+
error("Could not retrieve inverse sources")
46+
}
47+
}
48+
49+
/**
50+
* @return Bazel label corresponding to file path
51+
*
52+
* For example when you pass a relative path like "foo/Lib.kt", you will receive "//foo:Lib.kt".
53+
* Null is returned in case the file does not exist or does not belong to any target's sources list
54+
*/
55+
private fun fileLabel(
56+
relativePath: Path,
57+
bazelRunner: BazelRunner,
58+
cancelChecker: CancelChecker
59+
): String? {
60+
val fileLabelResult = bazelRunner.commandBuilder().query().withTargets(listOf(relativePath.toString()))
61+
.executeBazelCommand(null).waitAndGetResult(cancelChecker)
62+
return if (fileLabelResult.statusCode == StatusCode.OK && fileLabelResult.stdoutLines.size == 1) {
63+
fileLabelResult.stdoutLines.first()
64+
} else if (fileLabelResult.stderrLines.first().startsWith("ERROR: no such target '")) {
65+
null
66+
} else {
67+
throw RuntimeException("Could not find file. Bazel query failed:\n ${fileLabelResult.stderrLines.joinToString { "\n" }}\n")
68+
}
69+
}
70+
}

server/src/main/kotlin/org/jetbrains/bsp/bazel/server/sync/ProjectResolver.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class ProjectResolver(
7171
) { targetInfoReader.readTargetMapFromAspectOutputs(aspectOutputs) }
7272
return measured(
7373
"Mapping to internal model"
74-
) { bazelProjectMapper.createProject(targets, rootTargets.toSet(), allTargetNames, workspaceContext) }
74+
) { bazelProjectMapper.createProject(targets, rootTargets.toSet(), allTargetNames, workspaceContext, bazelInfo) }
7575
}
7676

7777
private fun buildProjectWithAspect(cancelChecker: CancelChecker, workspaceContext: WorkspaceContext): BazelBspAspectsManagerResult =

server/src/main/kotlin/org/jetbrains/bsp/bazel/server/sync/ProjectSyncService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class ProjectSyncService(private val bspMapper: BspProjectMapper, private val pr
8787
inverseSourcesParams: InverseSourcesParams
8888
): InverseSourcesResult {
8989
val project = projectProvider.get(cancelChecker)
90-
return bspMapper.inverseSources(project, inverseSourcesParams)
90+
return bspMapper.inverseSources(project, inverseSourcesParams, cancelChecker)
9191
}
9292

9393
fun buildTargetDependencySources(

server/src/main/kotlin/org/jetbrains/bsp/bazel/server/sync/model/Project.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.jetbrains.bsp.bazel.server.sync.model
22

3+
import org.jetbrains.bsp.bazel.bazelrunner.BazelInfo
4+
import org.jetbrains.bsp.bazel.bazelrunner.BazelRelease
35
import org.jetbrains.bsp.bazel.server.sync.languages.rust.RustModule
46
import java.net.URI
57

@@ -10,6 +12,7 @@ data class Project(
1012
val sourceToTarget: Map<URI, Label>,
1113
val libraries: Map<String, Library>,
1214
val invalidTargets: List<Label>,
15+
val bazelRelease: BazelRelease
1316
) {
1417
private val moduleMap: Map<Label, Module> = modules.associateBy(Module::label)
1518

server/src/test/kotlin/org/jetbrains/bsp/bazel/server/sync/ProjectStorageTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.jetbrains.bsp.bazel.server.sync
22

33
import io.kotest.matchers.shouldBe
4+
import org.jetbrains.bsp.bazel.bazelrunner.BazelRelease
45
import java.io.IOException
56
import java.net.URI
67
import org.jetbrains.bsp.bazel.logger.BspClientLogger
@@ -64,6 +65,7 @@ class ProjectStorageTest {
6465
mapOf(URI.create("file:///root/project/Lib.java") to Label("file:///root")),
6566
emptyMap(),
6667
emptyList(),
68+
BazelRelease(7),
6769
)
6870
storage.store(project)
6971
val loaded = storage.load()

0 commit comments

Comments
 (0)