Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix(java extractor): Handle source files in jars (#4188)
When we encounter a source file in a jar, don't try to add it as an
additional source path.

This includes a special case where the classpath is searched for sources
if no explicit sourcepath is given.

1) The URI generated by javac for files in a jar (JarFileObject) contains a
null path so the normal logic here will produce a null pointer exception.

2) The hooks into javac that we already have notice and record the source jar
usage, including the special case when it was specified as the classpath, not
the sourcepath.

Fixes #4186
  • Loading branch information
salguarnieri committed Nov 6, 2019
1 parent 14592b8 commit df711e3
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 1 deletion.
Expand Up @@ -413,7 +413,16 @@ private void getAdditionalSourcePaths(
// the correct sourcepath to add is the directory containing that
// package.
String packageSubDir = packageName.replace('.', '/');
String path = compilationUnit.getSourceFile().toUri().getPath();
URI uri = compilationUnit.getSourceFile().toUri();
// If the user included source files in their jars, we don't record anything special here
// because we pick up this source jar and the classpath/sourcepath usage with our other
// compiler hooks.
if ("jar".equals(uri.getScheme())) {
logger.atWarning().log(
"Detected a source in a jar file: %s - %s", uri, compilationUnit);
continue;
}
String path = uri.getPath();
// This needs to be lastIndexOf as there are source jars that
// contain the same package name in the files contained in them
// as the path the source jars live in. As we extract the source
Expand Down
Expand Up @@ -22,6 +22,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.devtools.kythe.extractors.shared.CompilationDescription;
import com.google.devtools.kythe.extractors.shared.ExtractionException;
import com.google.devtools.kythe.extractors.shared.ExtractorUtils;
import com.google.devtools.kythe.proto.Analysis.CompilationUnit;
import com.google.devtools.kythe.proto.Analysis.CompilationUnit.FileInput;
Expand Down Expand Up @@ -630,6 +631,47 @@ public void testEmptyCompilationUnit() throws Exception {
assertThat(details.getBootclasspathList()).containsExactly("!PLATFORM_CLASS_PATH_JAR!");
}

public void testSourceInJar() throws ExtractionException, InvalidProtocolBufferException {
JavaCompilationUnitExtractor java = new JavaCompilationUnitExtractor(CORPUS);

List<String> sources = testFiles("src_in_jar/C1.java");
List<String> classpath = ImmutableList.of(join(TEST_DATA_DIR, "src_in_jar/pack.jar"));

CompilationDescription description =
java.extract(
TARGET1,
sources,
classpath,
EMPTY,
EMPTY,
EMPTY,
EMPTY,
Optional.empty(),
EMPTY,
"output");

CompilationUnit unit = description.getCompilationUnit();
assertThat(unit).isNotNull();
assertThat(unit.getVName().getSignature()).isEqualTo(TARGET1);
assertThat(unit.getSourceFileCount()).isEqualTo(1);
assertThat(unit.getSourceFileList()).containsExactly(sources.get(0)).inOrder();

// Ensure the source jar and the class jar are included in the required inputs.
assertThat(getInfos(unit.getRequiredInputList()))
.containsAtLeast(
makeFileInfo(sources.get(0)),
makeFileInfo(
"!CLASS_PATH_JAR!/pack2/C3.class",
join(TEST_DATA_DIR, "src_in_jar/pack2/C3.class")),
makeFileInfo(
"!SOURCE_JAR!/pack/C2.java", join(TEST_DATA_DIR, "src_in_jar/pack/C2.java")));

JavaDetails details = getJavaDetails(unit);
assertThat(details.getSourcepathList()).containsExactly("!SOURCE_JAR!");
// Ensure the classpath is set for replay.
assertThat(details.getClasspathList()).containsExactly("!CLASS_PATH_JAR!");
}

private List<String> testFiles(String... files) {
List<String> res = new ArrayList<>();
for (String file : files) {
Expand Down
@@ -0,0 +1,6 @@
import pack.C2;
import pack2.C3;

class C1 {

}
@@ -0,0 +1,6 @@
This test tests that sources found in jars are handled properly.

The jar was built with:

javac pack2/C3.java
jar cf pack.jar pack/C2.java pack2/C3.class
Binary file not shown.
@@ -0,0 +1,5 @@
package pack;

public class C2 {

}
Binary file not shown.
@@ -0,0 +1,4 @@
package pack2;

public class C3 {
}

0 comments on commit df711e3

Please sign in to comment.