mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-06 10:42:45 +00:00
8381965: NullPointerException in TypeAnnotationPositions
Reviewed-by: mcimadamore
This commit is contained in:
parent
3f2002d488
commit
9acd9f8790
@ -25,6 +25,7 @@
|
||||
|
||||
package com.sun.tools.javac.comp;
|
||||
|
||||
import com.sun.source.tree.AnnotatedTypeTree;
|
||||
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
|
||||
import com.sun.source.tree.NewClassTree;
|
||||
import com.sun.tools.javac.code.*;
|
||||
@ -62,6 +63,7 @@ import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.sun.source.tree.MemberReferenceTree;
|
||||
import com.sun.source.tree.ModifiersTree;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMemberReference.OverloadKind;
|
||||
|
||||
@ -191,6 +193,19 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
result.pos = t.pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCTree visitAnnotatedType(AnnotatedTypeTree node, Void p) {
|
||||
return copy(((JCAnnotatedType) node).underlyingType, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JCTree visitModifiers(ModifiersTree node, Void p) {
|
||||
JCModifiers mods = (JCModifiers) super.visitModifiers(node, p);
|
||||
|
||||
mods.annotations = List.nil();
|
||||
return mods;
|
||||
}
|
||||
};
|
||||
deferredCopier = new TypeMapping<Void> () {
|
||||
@Override
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8371155 8379550 8384843
|
||||
* @bug 8371155 8379550 8381965 8384843
|
||||
* @summary Verify type annotations on local-like variables are propagated to
|
||||
* their types at an appropriate time.
|
||||
* @library /tools/lib
|
||||
@ -559,6 +559,192 @@ public class TypeAnnotationsOnVariables {
|
||||
" Test$TypeAnno");
|
||||
}
|
||||
|
||||
@Test
|
||||
void explicitLambdaHeader3() throws Exception {
|
||||
Path src = base.resolve("src");
|
||||
Path classes = base.resolve("classes");
|
||||
tb.writeJavaFiles(src,
|
||||
"""
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.List;
|
||||
|
||||
class Test {
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface TypeAnno { }
|
||||
|
||||
static final Consumer<List<@TypeAnno String>> TEST =
|
||||
id((List<@TypeAnno String> arg1) -> {});
|
||||
|
||||
private static <T> Consumer<T> id(Consumer<T> t) { return t;}
|
||||
private void test() {
|
||||
Object test =
|
||||
id((List<@TypeAnno String> arg2) -> {});
|
||||
}
|
||||
}
|
||||
""");
|
||||
Files.createDirectories(classes);
|
||||
List<String> actual = new ArrayList<>();
|
||||
new JavacTask(tb)
|
||||
.options("-d", classes.toString())
|
||||
.files(tb.findJavaFiles(src))
|
||||
.callback(task -> {
|
||||
task.addTaskListener(new TaskListener() {
|
||||
@Override
|
||||
public void finished(TaskEvent e) {
|
||||
if (e.getKind() != TaskEvent.Kind.ANALYZE) {
|
||||
return ;
|
||||
}
|
||||
Trees trees = Trees.instance(task);
|
||||
new TreePathScanner<Void, Void>() {
|
||||
@Override
|
||||
public Void visitVariable(VariableTree node, Void p) {
|
||||
actual.add(node.getName() + ": " + typeToString(trees.getTypeMirror(getCurrentPath())));
|
||||
return super.visitVariable(node, p);
|
||||
}
|
||||
@Override
|
||||
public Void visitLambdaExpression(LambdaExpressionTree node, Void p) {
|
||||
actual.add(treeToString(node)+ ": " + typeToString(trees.getTypeMirror(getCurrentPath())));
|
||||
return super.visitLambdaExpression(node, p);
|
||||
}
|
||||
}.scan(e.getCompilationUnit(), null);
|
||||
}
|
||||
});
|
||||
})
|
||||
.run()
|
||||
.writeAll();
|
||||
|
||||
List<String> expected = List.of(
|
||||
"TEST: java.util.function.Consumer<java.util.List<java.lang.@Test.TypeAnno String>>",
|
||||
"(List<@TypeAnno String> arg1)->{ }: java.util.function.Consumer<java.util.List<java.lang.String>>",
|
||||
"arg1: java.util.List<java.lang.@Test.TypeAnno String>",
|
||||
"t: java.util.function.Consumer<T>",
|
||||
"test: java.lang.Object",
|
||||
"(List<@TypeAnno String> arg2)->{ }: java.util.function.Consumer<java.util.List<java.lang.String>>",
|
||||
"arg2: java.util.List<java.lang.@Test.TypeAnno String>"
|
||||
);
|
||||
|
||||
actual.forEach(System.out::println);
|
||||
if (!expected.equals(actual)) {
|
||||
throw new AssertionError("Expected: " + expected + ", but got: " + actual);
|
||||
}
|
||||
|
||||
Path testClass = classes.resolve("Test.class");
|
||||
TestClassDesc testClassDesc = TestClassDesc.create(testClass);
|
||||
MethodModel clInit = singletonValue(testClassDesc.name2Method().get("<clinit>"));
|
||||
assertEmpty(getAnnotationsFromHeader(clInit));
|
||||
assertEmpty(getAnnotationsFromCode(clInit));
|
||||
MethodModel test = singletonValue(testClassDesc.name2Method().get("test"));
|
||||
assertEmpty(getAnnotationsFromHeader(test));
|
||||
assertEmpty(getAnnotationsFromCode(test));
|
||||
|
||||
checkTypeAnnotations(testClassDesc,
|
||||
"lambda$static$0",
|
||||
this::getAnnotationsFromHeader,
|
||||
" 0: LTest$TypeAnno;(): METHOD_FORMAL_PARAMETER, param_index=0, location=[TYPE_ARGUMENT(0)]",
|
||||
" Test$TypeAnno");
|
||||
|
||||
checkTypeAnnotations(testClassDesc,
|
||||
"lambda$test$0",
|
||||
this::getAnnotationsFromHeader,
|
||||
" 0: LTest$TypeAnno;(): METHOD_FORMAL_PARAMETER, param_index=0, location=[TYPE_ARGUMENT(0)]",
|
||||
" Test$TypeAnno");
|
||||
}
|
||||
|
||||
@Test
|
||||
void explicitLambdaHeader4() throws Exception {
|
||||
Path src = base.resolve("src");
|
||||
Path classes = base.resolve("classes");
|
||||
tb.writeJavaFiles(src,
|
||||
"""
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.List;
|
||||
|
||||
class Test {
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface TypeAnno { }
|
||||
|
||||
static final Consumer<List<String>> TEST =
|
||||
id((@TypeAnno List<String> arg) -> {});
|
||||
|
||||
private static <T> Consumer<T> id(Consumer<T> t) { return t;}
|
||||
private void test() {
|
||||
Object test =
|
||||
id((@TypeAnno List<String> arg) -> {});
|
||||
}
|
||||
}
|
||||
""");
|
||||
Files.createDirectories(classes);
|
||||
List<String> actual = new ArrayList<>();
|
||||
new JavacTask(tb)
|
||||
.options("-d", classes.toString())
|
||||
.files(tb.findJavaFiles(src))
|
||||
.callback(task -> {
|
||||
task.addTaskListener(new TaskListener() {
|
||||
@Override
|
||||
public void finished(TaskEvent e) {
|
||||
if (e.getKind() != TaskEvent.Kind.ANALYZE) {
|
||||
return ;
|
||||
}
|
||||
Trees trees = Trees.instance(task);
|
||||
new TreePathScanner<Void, Void>() {
|
||||
@Override
|
||||
public Void visitVariable(VariableTree node, Void p) {
|
||||
actual.add(node.getName() + ": " + typeToString(trees.getTypeMirror(getCurrentPath())));
|
||||
return super.visitVariable(node, p);
|
||||
}
|
||||
@Override
|
||||
public Void visitLambdaExpression(LambdaExpressionTree node, Void p) {
|
||||
actual.add(treeToString(node)+ ": " + typeToString(trees.getTypeMirror(getCurrentPath())));
|
||||
return super.visitLambdaExpression(node, p);
|
||||
}
|
||||
}.scan(e.getCompilationUnit(), null);
|
||||
}
|
||||
});
|
||||
})
|
||||
.run()
|
||||
.writeAll();
|
||||
|
||||
List<String> expected = List.of(
|
||||
"TEST: java.util.function.Consumer<java.util.List<java.lang.String>>",
|
||||
"(@TypeAnno List<String> arg)->{ }: java.util.function.Consumer<java.util.List<java.lang.String>>",
|
||||
"arg: java.util.@Test.TypeAnno List<java.lang.String>",
|
||||
"t: java.util.function.Consumer<T>",
|
||||
"test: java.lang.Object",
|
||||
"(@TypeAnno List<String> arg)->{ }: java.util.function.Consumer<java.util.List<java.lang.String>>",
|
||||
"arg: java.util.@Test.TypeAnno List<java.lang.String>"
|
||||
);
|
||||
|
||||
actual.forEach(System.out::println);
|
||||
if (!expected.equals(actual)) {
|
||||
throw new AssertionError("Expected: " + expected + ", but got: " + actual);
|
||||
}
|
||||
|
||||
Path testClass = classes.resolve("Test.class");
|
||||
TestClassDesc testClassDesc = TestClassDesc.create(testClass);
|
||||
MethodModel clInit = singletonValue(testClassDesc.name2Method().get("<clinit>"));
|
||||
assertEmpty(getAnnotationsFromHeader(clInit));
|
||||
assertEmpty(getAnnotationsFromCode(clInit));
|
||||
MethodModel test = singletonValue(testClassDesc.name2Method().get("test"));
|
||||
assertEmpty(getAnnotationsFromHeader(test));
|
||||
assertEmpty(getAnnotationsFromCode(test));
|
||||
|
||||
checkTypeAnnotations(testClassDesc,
|
||||
"lambda$static$0",
|
||||
this::getAnnotationsFromHeader,
|
||||
" 0: LTest$TypeAnno;(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
" Test$TypeAnno");
|
||||
|
||||
checkTypeAnnotations(testClassDesc,
|
||||
"lambda$test$0",
|
||||
this::getAnnotationsFromHeader,
|
||||
" 0: LTest$TypeAnno;(): METHOD_FORMAL_PARAMETER, param_index=0",
|
||||
" Test$TypeAnno");
|
||||
}
|
||||
|
||||
private void checkTypeAnnotations(TestClassDesc testClassDesc,
|
||||
String lambdaMethodName,
|
||||
String... expectedEntries) throws IOException {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user