
com.sourcegraph.scip_semanticdb.BazelBuildTool Maven / Gradle / Ivy
package com.sourcegraph.scip_semanticdb;
import com.sourcegraph.scip_java.Bazelbuild;
import com.sourcegraph.lsif_protocol.LsifToolInfo;
import java.io.*;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class BazelBuildTool {
public static int runAndReturnExitCode(String[] args) throws IOException, InterruptedException {
Optional maybeOptions = BazelOptions.parse(args);
if (!maybeOptions.isPresent()) {
return 1;
}
BazelOptions options = maybeOptions.get();
if (options.isHelp) {
BazelOptions.printHelp();
return 0;
}
if (options.isVersion) {
System.out.println(
"This command-line tool has no version because it is supposed to be compiled from source.");
return 0;
}
List mavenPackages = mavenPackages(options);
ScipSemanticdbReporter reporter =
new ScipSemanticdbReporter() {
private boolean hasErrors = false;
@Override
public void error(Throwable e) {
e.printStackTrace(System.err);
hasErrors = true;
}
@Override
public void error(String message) {
System.err.println("ERROR[scip-semanticdb]: " + message);
hasErrors = true;
}
@Override
public boolean hasErrors() {
return this.hasErrors;
}
};
ScipSemanticdbOptions scipOptions =
new ScipSemanticdbOptions(
options.targetroots,
options.output,
options.sourceroot,
reporter,
LsifToolInfo.newBuilder().setName("scip-java").setVersion("HEAD").build(),
"java",
ScipOutputFormat.TYPED_PROTOBUF,
options.parallel,
mavenPackages,
/* buildKind */ "",
/* emitInverseRelationships */ true,
/* allowEmptyIndex */ true,
/* indexDirectoryEntries */ false // because Bazel only compiles to jar files.
);
ScipSemanticdb.run(scipOptions);
if (!scipOptions.reporter.hasErrors()) {
System.out.println("done: " + scipOptions.output);
return 0;
} else {
System.out.println("SCIP index generation failed");
return 1;
}
}
public static List mavenPackages(BazelOptions options)
throws IOException, InterruptedException {
ArrayList result = new ArrayList<>();
if (!options.isQueryMavenImports) {
return result;
}
Bazelbuild.QueryResult jvmImports = runBazelQuery(options, "kind('.*_import', @maven//...)");
Path baseDirectory =
options.sourceroot.resolve("bazel-bin").resolve("external").resolve("maven");
PathMatcher jarPattern = FileSystems.getDefault().getPathMatcher("glob:**.jar");
for (Bazelbuild.Target target : jvmImports.getTargetList()) {
if (target.getType() != Bazelbuild.Target.Discriminator.RULE) {
continue;
}
Bazelbuild.Rule rule = target.getRule();
MavenPackage basePackage = null;
List jarDirectories = new ArrayList<>();
for (Bazelbuild.Attribute attribute : rule.getAttributeList()) {
if (attribute.getName().equals("jars")) {
for (String tag : attribute.getStringListValueList()) {
if (tag.startsWith("@maven//:")) {
jarDirectories.add(
baseDirectory.resolve(tag.substring("@maven//:".length())).getParent());
}
}
}
if (attribute.getName().equals("tags")) {
for (String tag : attribute.getStringListValueList()) {
if (tag.startsWith("maven_coordinates=")) {
String[] parts = tag.substring("maven_coordinates=".length()).split(":");
if (parts.length == 3) {
// The jar part is populated via `withJar()` below.
basePackage = new MavenPackage(/* jar= */ null, parts[0], parts[1], parts[2]);
}
}
}
}
}
if (basePackage == null) {
continue;
}
for (Path directory : jarDirectories) {
try (Stream list = Files.list(directory)) {
List jars = list.filter(jarPattern::matches).collect(Collectors.toList());
for (Path jar : jars) {
result.add(basePackage.withJar(jar));
}
}
}
}
return result;
}
public static Bazelbuild.QueryResult runBazelQuery(BazelOptions options, String query)
throws IOException, InterruptedException {
List command = Arrays.asList(options.bazelBinary, "query", query, "--output=proto");
System.out.println("running: " + String.join(" ", command));
Process bazelQuery = new ProcessBuilder(command).directory(options.sourceroot.toFile()).start();
byte[] bytes = InputStreamBytes.readAll(bazelQuery.getInputStream());
int exitValue = bazelQuery.waitFor();
if (exitValue != 0) {
throw new RuntimeException("bazel command failed\n" + new String(bytes));
}
return Bazelbuild.QueryResult.parseFrom(bytes);
}
public static void main(String[] args) throws IOException, InterruptedException {
System.exit(runAndReturnExitCode(args));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy