Skip to content

Commit 00c8ed5

Browse files
authored
Merge pull request #611 from sourcegraph/olafurpg/no-relative-path
Add `-no-relative-path:` flag to control indexing of generated files
2 parents 5028089 + 9e9451d commit 00c8ed5

File tree

5 files changed

+117
-40
lines changed

5 files changed

+117
-40
lines changed

semanticdb-javac/defs.bzl

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
"""Java rules that automatically register the SemanticDB compiler plugin based on the presence of a string flag."""
2-
load("@rules_java//java:defs.bzl", native_java_library="java_library", native_java_binary="java_binary")
32

4-
def java_library(javacopts=[], plugins=[],**kwargs):
5-
native_java_library(
6-
javacopts=_actual_javacopts(javacopts),
7-
plugins=_actual_plugins(plugins),
8-
**kwargs)
3+
load("@rules_java//java:defs.bzl", native_java_binary = "java_binary", native_java_library = "java_library")
94

5+
def java_library(javacopts = [], plugins = [], **kwargs):
6+
native_java_library(
7+
javacopts = _actual_javacopts(javacopts),
8+
plugins = _actual_plugins(plugins),
9+
**kwargs
10+
)
1011

11-
def java_binary(javacopts=[], plugins=[],**kwargs):
12+
def java_binary(javacopts = [], plugins = [], **kwargs):
1213
native_java_binary(
13-
javacopts=_actual_javacopts(javacopts),
14-
plugins=_actual_plugins(plugins),
15-
**kwargs)
14+
javacopts = _actual_javacopts(javacopts),
15+
plugins = _actual_plugins(plugins),
16+
**kwargs
17+
)
1618

1719
def _actual_javacopts(javacopts):
1820
return select({
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.sourcegraph.semanticdb_javac;
2+
3+
/**
4+
* Configuration options to determine how semanticdb-javac should handle files that have no good
5+
* relative paths.
6+
*
7+
* <p>When indexing a file at an absolute path /project/src/main/example/Foo.java, SemanticDB needs
8+
* to know the "sourceroot" path /project in order to relativize the path of the source file into
9+
* src/main/example/Foo.java. This configuration option determines what the compiler plugin should
10+
* do when it's not able to find a good relative path.
11+
*/
12+
public enum NoRelativePathMode {
13+
14+
/**
15+
* Come up with a unique relative path for the SemanticDB path with no guarantee that this path
16+
* corresponds to the original path of the generated source file.
17+
*/
18+
INDEX_ANYWAY,
19+
20+
/** Silently ignore the file, don't index it. */
21+
SKIP,
22+
23+
/** Report an error message and fail the compilation. */
24+
ERROR,
25+
26+
/** Ignore the file, but print a message explaining it's ignored. */
27+
WARNING
28+
}

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbJavacOptions.java

+28
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import java.nio.file.Path;
66
import java.nio.file.Paths;
77
import java.util.ArrayList;
8+
import java.util.Arrays;
9+
import java.util.stream.Collectors;
810
import javax.tools.FileObject;
911
import javax.tools.JavaFileManager;
1012
import javax.tools.JavaFileObject;
@@ -26,6 +28,7 @@ public class SemanticdbJavacOptions {
2628
public final ArrayList<String> errors;
2729
public boolean alreadyReportedErrors = false;
2830
public UriScheme uriScheme = UriScheme.DEFAULT;
31+
public NoRelativePathMode noRelativePath = NoRelativePathMode.INDEX_ANYWAY;
2932
public Path generatedTargetRoot;
3033

3134
public static String stubClassName = "META-INF-semanticdb-stub";
@@ -60,6 +63,31 @@ public static SemanticdbJavacOptions parse(String[] args, Context ctx) {
6063
result.sourceroot = Paths.get(arg.substring("-sourceroot:".length())).normalize();
6164
} else if (arg.equals("-build-tool:sbt") || arg.equals("-build-tool:mill")) {
6265
result.uriScheme = UriScheme.ZINC;
66+
} else if (arg.startsWith("-no-relative-path:")) {
67+
String value = arg.substring("-no-relative-path:".length());
68+
switch (value) {
69+
case "index_anyway":
70+
result.noRelativePath = NoRelativePathMode.INDEX_ANYWAY;
71+
break;
72+
case "skip":
73+
result.noRelativePath = NoRelativePathMode.SKIP;
74+
break;
75+
case "error":
76+
result.noRelativePath = NoRelativePathMode.ERROR;
77+
break;
78+
case "warning":
79+
result.noRelativePath = NoRelativePathMode.WARNING;
80+
break;
81+
default:
82+
String validValues =
83+
Arrays.stream(NoRelativePathMode.values())
84+
.map(NoRelativePathMode::toString)
85+
.collect(Collectors.joining(", "));
86+
result.errors.add(
87+
String.format(
88+
"unknown -no-relative-path mode '%s'. Valid values are %s.",
89+
value, validValues));
90+
}
6391
} else if (arg.equals("-build-tool:bazel")) {
6492
result.uriScheme = UriScheme.BAZEL;
6593
useJavacClassesDir = true;

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbTaskListener.java

+40-28
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import com.sun.source.util.Trees;
77
import com.sun.tools.javac.model.JavacTypes;
88

9-
import javax.tools.Diagnostic;
109
import javax.tools.JavaFileObject;
1110
import java.io.IOException;
1211
import java.net.URI;
@@ -25,7 +24,7 @@ public final class SemanticdbTaskListener implements TaskListener {
2524
private final SemanticdbReporter reporter;
2625
private final JavacTypes javacTypes;
2726
private final Trees trees;
28-
private boolean sourceGeneratorsMessageIsLogged = false;
27+
private int noRelativePathCounter = 0;
2928

3029
public SemanticdbTaskListener(
3130
SemanticdbJavacOptions options,
@@ -130,7 +129,11 @@ public static Path absolutePathFromUri(SemanticdbJavacOptions options, JavaFileO
130129
new String[] {"SimpleFileObject[", "DirectoryFileObject["};
131130
for (String pattern : knownBazelToStringPatterns) {
132131
if (toString.startsWith(pattern) && toString.endsWith("]")) {
133-
return Paths.get(toString.substring(pattern.length(), toString.length() - 1));
132+
Path path = Paths.get(toString.substring(pattern.length(), toString.length() - 1));
133+
if (path.isAbsolute()) {
134+
return path;
135+
}
136+
return options.sourceroot.resolve(path);
134137
}
135138
}
136139
throw new IllegalArgumentException("unsupported source file: " + toString);
@@ -190,32 +193,41 @@ private Result<Path, String> semanticdbOutputPath(SemanticdbJavacOptions options
190193
.resolve(relativePath)
191194
.resolveSibling(filename);
192195
return Result.ok(semanticdbOutputPath);
193-
} else {
194-
195-
if (options.uriScheme == UriScheme.BAZEL && options.generatedTargetRoot != null) {
196-
try {
197-
if (absolutePath.toRealPath().startsWith(options.generatedTargetRoot)) {
198-
if (!sourceGeneratorsMessageIsLogged) {
199-
sourceGeneratorsMessageIsLogged = true;
200-
reporter.info(
201-
"Usage of source generators detected - scip-java does not produce SemanticDB files for generated files.\n"
202-
+ "This message is logged only once",
203-
e);
204-
}
205-
206-
return null;
207-
}
208-
} catch (IOException exc) {
209-
reporter.exception(exc, e);
210-
return null;
211-
}
212-
}
196+
}
213197

214-
return Result.error(
215-
String.format(
216-
"sourceroot '%s does not contain path '%s'. To fix this problem, update the -sourceroot flag to "
217-
+ "be a parent directory of this source file.",
218-
options.sourceroot, absolutePath));
198+
switch (options.noRelativePath) {
199+
case INDEX_ANYWAY:
200+
// Come up with a unique relative path for this file even if it's not under the sourceroot.
201+
// By indexing auto-generated files, we collect SymbolInformation for auto-generated symbol,
202+
// which results in more useful hover tooltips in the editor.
203+
// In the future, we may want to additionally embed the full text contents of these files
204+
// so that it's possible to browse generated files with precise code navigation.
205+
String uniqueFilename =
206+
String.format("%d.%s.semanticdb", ++noRelativePathCounter, absolutePath.getFileName());
207+
Path semanticdbOutputPath =
208+
options
209+
.targetroot
210+
.resolve("META-INF")
211+
.resolve("semanticdb")
212+
.resolve("no-relative-path")
213+
.resolve(uniqueFilename);
214+
return Result.ok(semanticdbOutputPath);
215+
case WARNING:
216+
reporter.info(
217+
String.format(
218+
"Skipping file '%s' because it is not under the sourceroot '%s'",
219+
absolutePath, options.sourceroot),
220+
e);
221+
case SKIP:
222+
return null;
223+
case ERROR:
224+
default:
225+
return Result.error(
226+
String.format(
227+
"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. "
228+
+ "To fix this problem, either configure the -sourceroot:PATH flag to be the parent directory of all indexed files, or "
229+
+ "configure -no-relative-path:VALUE flag to have one of the following values: index_anyway, skip, warning.",
230+
absolutePath));
219231
}
220232
}
221233
}

semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,12 @@ private Semanticdb.Access semanticdbAccess(Symbol sym) {
436436

437437
private String semanticdbUri() {
438438
Path absolutePath = SemanticdbTaskListener.absolutePathFromUri(options, event.getSourceFile());
439-
Path relativePath = options.sourceroot.relativize(absolutePath);
439+
Path uriPath =
440+
absolutePath.startsWith(options.sourceroot)
441+
? options.sourceroot.relativize(absolutePath)
442+
: absolutePath;
440443
StringBuilder out = new StringBuilder();
441-
Iterator<Path> it = relativePath.iterator();
444+
Iterator<Path> it = uriPath.iterator();
442445
if (it.hasNext()) out.append(it.next().getFileName().toString());
443446
while (it.hasNext()) {
444447
Path part = it.next();
@@ -447,6 +450,10 @@ private String semanticdbUri() {
447450
return out.toString();
448451
}
449452

453+
private Path semanticdbPath() {
454+
return SemanticdbTaskListener.absolutePathFromUri(options, event.getSourceFile());
455+
}
456+
450457
private Semanticdb.Documentation semanticdbDocumentation(Symbol sym) {
451458
try {
452459
Elements elements = task.getElements();

0 commit comments

Comments
 (0)