-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
26
This is closely related to https://bugs.openjdk.org/browse/JDK-8351431.
The repro is the same as the previous bug except it is an anonymous new class expression: `new Test<@TA String>() {}` instead of `new Test<@TA String>()`
The expected output is:
Tree: new Test<@TA String>(){...}, Type: <anonymous Test<java.lang.@Test.TA String>>
The actual output is:
Tree: new Test<@TA String>(){...}, Type: <anonymous Test<java.lang. String>>
I think the issue is that as part of the fix forJDK-8198945, Annotate doesn't process type annotations on anonymous class types when visited through NewClassTrees. That successfully prevents Annotate from attaching those annotations to the enclosing method of the NewClassTree, which would be incorrect. However it also prevents them from being entered, and means they aren't present on the type for the NewClassTree, as the repro shows.
https://github.com/openjdk/jdk/blame/7c22b814d670deda6c2bb93b1e150975c27a165f/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java#L1162-L1164
```
import com.sun.source.tree.NewClassTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import javax.lang.model.type.TypeMirror;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public final class Z {
public static void main(final String[] args) throws IOException {
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager =
compiler.getStandardFileManager(null, Locale.ENGLISH, StandardCharsets.UTF_8);
final JavacTask task =
(JavacTask)
compiler.getTask(null, null, null, null, null, fileManager.getJavaFileObjects(args));
task.addTaskListener(
new TaskListener() {
@Override
public void finished(TaskEvent e) {
if (e.getKind() == TaskEvent.Kind.ANALYZE) {
new TreePathScanner<Void, Void>() {
@Override
public Void visitNewClass(NewClassTree tree, Void unused) {
TypeMirror type = Trees.instance(task).getTypeMirror(getCurrentPath());
System.err.printf("Tree: %s, Type: %s\n", tree, type);
return super.visitNewClass(tree, unused);
}
}.scan(e.getCompilationUnit(), null);
}
}
});
task.analyze();
}
}
```
```
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
class Test<T> {
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TA {}
public void testMethod() {
new Test<@TA String>() {};
}
}
```
The repro is the same as the previous bug except it is an anonymous new class expression: `new Test<@TA String>() {}` instead of `new Test<@TA String>()`
The expected output is:
Tree: new Test<@TA String>(){...}, Type: <anonymous Test<java.lang.@Test.TA String>>
The actual output is:
Tree: new Test<@TA String>(){...}, Type: <anonymous Test<java.lang. String>>
I think the issue is that as part of the fix for
https://github.com/openjdk/jdk/blame/7c22b814d670deda6c2bb93b1e150975c27a165f/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java#L1162-L1164
```
import com.sun.source.tree.NewClassTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import javax.lang.model.type.TypeMirror;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public final class Z {
public static void main(final String[] args) throws IOException {
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager =
compiler.getStandardFileManager(null, Locale.ENGLISH, StandardCharsets.UTF_8);
final JavacTask task =
(JavacTask)
compiler.getTask(null, null, null, null, null, fileManager.getJavaFileObjects(args));
task.addTaskListener(
new TaskListener() {
@Override
public void finished(TaskEvent e) {
if (e.getKind() == TaskEvent.Kind.ANALYZE) {
new TreePathScanner<Void, Void>() {
@Override
public Void visitNewClass(NewClassTree tree, Void unused) {
TypeMirror type = Trees.instance(task).getTypeMirror(getCurrentPath());
System.err.printf("Tree: %s, Type: %s\n", tree, type);
return super.visitNewClass(tree, unused);
}
}.scan(e.getCompilationUnit(), null);
}
}
});
task.analyze();
}
}
```
```
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
class Test<T> {
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface TA {}
public void testMethod() {
new Test<@TA String>() {};
}
}
```
- relates to
-
JDK-8198945 Invalid RuntimeVisibleTypeAnnotations for annotation on anonymous class type parameter
-
- Resolved
-
-
JDK-8351431 Type annotations on new class creation expressions can't be retrieved
-
- Resolved
-
- links to
-
Review(master) openjdk/jdk/27730