Skip to content

Commit 260f1bb

Browse files
cushonJavac Team
authored andcommitted
Model types of elements that are missing from the classpath as ERROR types
This fixes a bug where if a class file referenced an annotation that wasn't on the classpath, turbine would model that annotation's type as a non-ERROR type, and then report a fatal error trying to load the missing class file. This changes causes it to model the missing type as an ERROR type, preventing it from incorrectly trying to access additional information about the missing class. PiperOrigin-RevId: 586861763
1 parent cf3b973 commit 260f1bb

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

java/com/google/turbine/processing/TurbineElement.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,10 @@ public TypeMirror get() {
338338
return factory.asTypeMirror(asGenericType(sym));
339339
}
340340

341-
ClassTy asGenericType(ClassSymbol symbol) {
341+
Type asGenericType(ClassSymbol symbol) {
342342
TypeBoundClass info = info();
343343
if (info == null) {
344-
return ClassTy.asNonParametricClassTy(symbol);
344+
return ErrorTy.create(getQualifiedName().toString());
345345
}
346346
Deque<Type.ClassTy.SimpleClassTy> simples = new ArrayDeque<>();
347347
simples.addFirst(simple(symbol, info));

javatests/com/google/turbine/processing/ProcessingIntegrationTest.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,29 @@
3737
import com.google.turbine.binder.ClassPathBinder;
3838
import com.google.turbine.binder.Processing;
3939
import com.google.turbine.binder.Processing.ProcessorInfo;
40+
import com.google.turbine.binder.sym.ClassSymbol;
4041
import com.google.turbine.diag.SourceFile;
4142
import com.google.turbine.diag.TurbineDiagnostic;
4243
import com.google.turbine.diag.TurbineError;
44+
import com.google.turbine.diag.TurbineLog;
4345
import com.google.turbine.lower.IntegrationTestSupport;
4446
import com.google.turbine.parse.Parser;
4547
import com.google.turbine.testing.TestClassPaths;
4648
import com.google.turbine.tree.Tree;
4749
import java.io.IOException;
50+
import java.io.OutputStream;
4851
import java.io.PrintWriter;
4952
import java.io.UncheckedIOException;
5053
import java.io.Writer;
5154
import java.net.URI;
55+
import java.nio.file.Files;
5256
import java.nio.file.Path;
5357
import java.nio.file.Paths;
58+
import java.util.Map;
5459
import java.util.Optional;
5560
import java.util.Set;
61+
import java.util.jar.JarEntry;
62+
import java.util.jar.JarOutputStream;
5663
import javax.annotation.processing.AbstractProcessor;
5764
import javax.annotation.processing.ProcessingEnvironment;
5865
import javax.annotation.processing.RoundEnvironment;
@@ -62,18 +69,23 @@
6269
import javax.lang.model.element.Element;
6370
import javax.lang.model.element.ExecutableElement;
6471
import javax.lang.model.element.TypeElement;
72+
import javax.lang.model.type.DeclaredType;
6573
import javax.lang.model.type.ExecutableType;
6674
import javax.tools.Diagnostic;
6775
import javax.tools.FileObject;
6876
import javax.tools.JavaFileObject;
6977
import javax.tools.StandardLocation;
78+
import org.junit.Rule;
7079
import org.junit.Test;
80+
import org.junit.rules.TemporaryFolder;
7181
import org.junit.runner.RunWith;
7282
import org.junit.runners.JUnit4;
7383

7484
@RunWith(JUnit4.class)
7585
public class ProcessingIntegrationTest {
7686

87+
@Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();
88+
7789
@SupportedAnnotationTypes("*")
7890
public static class CrashingProcessor extends AbstractProcessor {
7991

@@ -864,4 +876,74 @@ public void uriProcessing() throws IOException {
864876
.map(d -> d.message()))
865877
.containsExactly("file:///foo/Bar - " + Paths.get(URI.create("file:///foo/Bar")));
866878
}
879+
880+
@SupportedAnnotationTypes("*")
881+
public static class MethodAnnotationTypeKindProcessor extends AbstractProcessor {
882+
@Override
883+
public SourceVersion getSupportedSourceVersion() {
884+
return SourceVersion.latestSupported();
885+
}
886+
887+
boolean first = true;
888+
889+
@Override
890+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
891+
if (!first) {
892+
return false;
893+
}
894+
first = false;
895+
TypeElement e = processingEnv.getElementUtils().getTypeElement("T");
896+
for (AnnotationMirror a : e.getAnnotationMirrors()) {
897+
DeclaredType t = a.getAnnotationType();
898+
processingEnv
899+
.getMessager()
900+
.printMessage(Diagnostic.Kind.NOTE, t + "(" + t.getKind() + ")", e);
901+
// this shouldn't crash
902+
requireNonNull(a.getAnnotationType().asElement().getEnclosedElements());
903+
}
904+
return false;
905+
}
906+
}
907+
908+
@Test
909+
public void missingAnnotationType() throws IOException {
910+
Map<String, byte[]> library =
911+
IntegrationTestSupport.runTurbine(
912+
ImmutableMap.of(
913+
"A.java", //
914+
"@interface A {}",
915+
"T.java",
916+
"@A class T {}"),
917+
ImmutableList.of());
918+
Path libJar = temporaryFolder.newFile("lib.jar").toPath();
919+
try (OutputStream os = Files.newOutputStream(libJar);
920+
JarOutputStream jos = new JarOutputStream(os)) {
921+
// deliberately exclude the definition of the annotation
922+
jos.putNextEntry(new JarEntry("T.class"));
923+
jos.write(requireNonNull(library.get("T")));
924+
}
925+
926+
ImmutableList<Tree.CompUnit> units =
927+
parseUnit(
928+
"=== Y.java ===", //
929+
"class Y {}");
930+
931+
TurbineLog log = new TurbineLog();
932+
BindingResult bound =
933+
Binder.bind(
934+
log,
935+
units,
936+
ClassPathBinder.bindClasspath(ImmutableList.of(libJar)),
937+
ProcessorInfo.create(
938+
ImmutableList.of(new MethodAnnotationTypeKindProcessor()),
939+
getClass().getClassLoader(),
940+
ImmutableMap.of(),
941+
SourceVersion.latestSupported()),
942+
TestClassPaths.TURBINE_BOOTCLASSPATH,
943+
Optional.empty());
944+
assertThat(bound.units().keySet()).containsExactly(new ClassSymbol("Y"));
945+
ImmutableList<String> messages =
946+
log.diagnostics().stream().map(TurbineDiagnostic::message).collect(toImmutableList());
947+
assertThat(messages).containsExactly("A(ERROR)");
948+
}
867949
}

0 commit comments

Comments
 (0)