diff --git a/semanticdb-javac/defs.bzl b/semanticdb-javac/defs.bzl
index 8890eb97..1323219b 100644
--- a/semanticdb-javac/defs.bzl
+++ b/semanticdb-javac/defs.bzl
@@ -1,18 +1,20 @@
"""Java rules that automatically register the SemanticDB compiler plugin based on the presence of a string flag."""
-load("@rules_java//java:defs.bzl", native_java_library="java_library", native_java_binary="java_binary")
-def java_library(javacopts=[], plugins=[],**kwargs):
- native_java_library(
- javacopts=_actual_javacopts(javacopts),
- plugins=_actual_plugins(plugins),
- **kwargs)
+load("@rules_java//java:defs.bzl", native_java_binary = "java_binary", native_java_library = "java_library")
+def java_library(javacopts = [], plugins = [], **kwargs):
+ native_java_library(
+ javacopts = _actual_javacopts(javacopts),
+ plugins = _actual_plugins(plugins),
+ **kwargs
+ )
-def java_binary(javacopts=[], plugins=[],**kwargs):
+def java_binary(javacopts = [], plugins = [], **kwargs):
native_java_binary(
- javacopts=_actual_javacopts(javacopts),
- plugins=_actual_plugins(plugins),
- **kwargs)
+ javacopts = _actual_javacopts(javacopts),
+ plugins = _actual_plugins(plugins),
+ **kwargs
+ )
def _actual_javacopts(javacopts):
return select({
diff --git a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/NoRelativePathMode.java b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/NoRelativePathMode.java
new file mode 100644
index 00000000..89277ea9
--- /dev/null
+++ b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/NoRelativePathMode.java
@@ -0,0 +1,28 @@
+package com.sourcegraph.semanticdb_javac;
+
+/**
+ * Configuration options to determine how semanticdb-javac should handle files that have no good
+ * relative paths.
+ *
+ *
When indexing a file at an absolute path /project/src/main/example/Foo.java, SemanticDB needs
+ * to know the "sourceroot" path /project in order to relativize the path of the source file into
+ * src/main/example/Foo.java. This configuration option determines what the compiler plugin should
+ * do when it's not able to find a good relative path.
+ */
+public enum NoRelativePathMode {
+
+ /**
+ * Come up with a unique relative path for the SemanticDB path with no guarantee that this path
+ * corresponds to the original path of the generated source file.
+ */
+ INDEX_ANYWAY,
+
+ /** Silently ignore the file, don't index it. */
+ SKIP,
+
+ /** Report an error message and fail the compilation. */
+ ERROR,
+
+ /** Ignore the file, but print a message explaining it's ignored. */
+ WARNING
+}
diff --git a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbJavacOptions.java b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbJavacOptions.java
index e6ed2c16..da03ffaf 100644
--- a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbJavacOptions.java
+++ b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbJavacOptions.java
@@ -5,6 +5,8 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.stream.Collectors;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
@@ -26,6 +28,7 @@ public class SemanticdbJavacOptions {
public final ArrayList errors;
public boolean alreadyReportedErrors = false;
public UriScheme uriScheme = UriScheme.DEFAULT;
+ public NoRelativePathMode noRelativePath = NoRelativePathMode.INDEX_ANYWAY;
public Path generatedTargetRoot;
public static String stubClassName = "META-INF-semanticdb-stub";
@@ -60,6 +63,31 @@ public static SemanticdbJavacOptions parse(String[] args, Context ctx) {
result.sourceroot = Paths.get(arg.substring("-sourceroot:".length())).normalize();
} else if (arg.equals("-build-tool:sbt") || arg.equals("-build-tool:mill")) {
result.uriScheme = UriScheme.ZINC;
+ } else if (arg.startsWith("-no-relative-path:")) {
+ String value = arg.substring("-no-relative-path:".length());
+ switch (value) {
+ case "index_anyway":
+ result.noRelativePath = NoRelativePathMode.INDEX_ANYWAY;
+ break;
+ case "skip":
+ result.noRelativePath = NoRelativePathMode.SKIP;
+ break;
+ case "error":
+ result.noRelativePath = NoRelativePathMode.ERROR;
+ break;
+ case "warning":
+ result.noRelativePath = NoRelativePathMode.WARNING;
+ break;
+ default:
+ String validValues =
+ Arrays.stream(NoRelativePathMode.values())
+ .map(NoRelativePathMode::toString)
+ .collect(Collectors.joining(", "));
+ result.errors.add(
+ String.format(
+ "unknown -no-relative-path mode '%s'. Valid values are %s.",
+ value, validValues));
+ }
} else if (arg.equals("-build-tool:bazel")) {
result.uriScheme = UriScheme.BAZEL;
useJavacClassesDir = true;
diff --git a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbTaskListener.java b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbTaskListener.java
index f46df649..e7b7a11e 100644
--- a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbTaskListener.java
+++ b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbTaskListener.java
@@ -6,7 +6,6 @@
import com.sun.source.util.Trees;
import com.sun.tools.javac.model.JavacTypes;
-import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.net.URI;
@@ -25,7 +24,7 @@ public final class SemanticdbTaskListener implements TaskListener {
private final SemanticdbReporter reporter;
private final JavacTypes javacTypes;
private final Trees trees;
- private boolean sourceGeneratorsMessageIsLogged = false;
+ private int noRelativePathCounter = 0;
public SemanticdbTaskListener(
SemanticdbJavacOptions options,
@@ -130,7 +129,11 @@ public static Path absolutePathFromUri(SemanticdbJavacOptions options, JavaFileO
new String[] {"SimpleFileObject[", "DirectoryFileObject["};
for (String pattern : knownBazelToStringPatterns) {
if (toString.startsWith(pattern) && toString.endsWith("]")) {
- return Paths.get(toString.substring(pattern.length(), toString.length() - 1));
+ Path path = Paths.get(toString.substring(pattern.length(), toString.length() - 1));
+ if (path.isAbsolute()) {
+ return path;
+ }
+ return options.sourceroot.resolve(path);
}
}
throw new IllegalArgumentException("unsupported source file: " + toString);
@@ -190,32 +193,41 @@ private Result semanticdbOutputPath(SemanticdbJavacOptions options
.resolve(relativePath)
.resolveSibling(filename);
return Result.ok(semanticdbOutputPath);
- } else {
-
- if (options.uriScheme == UriScheme.BAZEL && options.generatedTargetRoot != null) {
- try {
- if (absolutePath.toRealPath().startsWith(options.generatedTargetRoot)) {
- if (!sourceGeneratorsMessageIsLogged) {
- sourceGeneratorsMessageIsLogged = true;
- reporter.info(
- "Usage of source generators detected - scip-java does not produce SemanticDB files for generated files.\n"
- + "This message is logged only once",
- e);
- }
-
- return null;
- }
- } catch (IOException exc) {
- reporter.exception(exc, e);
- return null;
- }
- }
+ }
- return Result.error(
- String.format(
- "sourceroot '%s does not contain path '%s'. To fix this problem, update the -sourceroot flag to "
- + "be a parent directory of this source file.",
- options.sourceroot, absolutePath));
+ switch (options.noRelativePath) {
+ case INDEX_ANYWAY:
+ // Come up with a unique relative path for this file even if it's not under the sourceroot.
+ // By indexing auto-generated files, we collect SymbolInformation for auto-generated symbol,
+ // which results in more useful hover tooltips in the editor.
+ // In the future, we may want to additionally embed the full text contents of these files
+ // so that it's possible to browse generated files with precise code navigation.
+ String uniqueFilename =
+ String.format("%d.%s.semanticdb", ++noRelativePathCounter, absolutePath.getFileName());
+ Path semanticdbOutputPath =
+ options
+ .targetroot
+ .resolve("META-INF")
+ .resolve("semanticdb")
+ .resolve("no-relative-path")
+ .resolve(uniqueFilename);
+ return Result.ok(semanticdbOutputPath);
+ case WARNING:
+ reporter.info(
+ String.format(
+ "Skipping file '%s' because it is not under the sourceroot '%s'",
+ absolutePath, options.sourceroot),
+ e);
+ case SKIP:
+ return null;
+ case ERROR:
+ default:
+ return Result.error(
+ String.format(
+ "Unable to detect the relative path of '%s'. A common reason for this error is that the file is that this file is auto-generated. "
+ + "To fix this problem, either configure the -sourceroot:PATH flag to be the parent directory of all indexed files, or "
+ + "configure -no-relative-path:VALUE flag to have one of the following values: index_anyway, skip, warning.",
+ absolutePath));
}
}
}
diff --git a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java
index 120b449e..efbdf3fe 100644
--- a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java
+++ b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java
@@ -436,9 +436,12 @@ private Semanticdb.Access semanticdbAccess(Symbol sym) {
private String semanticdbUri() {
Path absolutePath = SemanticdbTaskListener.absolutePathFromUri(options, event.getSourceFile());
- Path relativePath = options.sourceroot.relativize(absolutePath);
+ Path uriPath =
+ absolutePath.startsWith(options.sourceroot)
+ ? options.sourceroot.relativize(absolutePath)
+ : absolutePath;
StringBuilder out = new StringBuilder();
- Iterator it = relativePath.iterator();
+ Iterator it = uriPath.iterator();
if (it.hasNext()) out.append(it.next().getFileName().toString());
while (it.hasNext()) {
Path part = it.next();
@@ -447,6 +450,10 @@ private String semanticdbUri() {
return out.toString();
}
+ private Path semanticdbPath() {
+ return SemanticdbTaskListener.absolutePathFromUri(options, event.getSourceFile());
+ }
+
private Semanticdb.Documentation semanticdbDocumentation(Symbol sym) {
try {
Elements elements = task.getElements();