8247334: Trees.getScope crashes for annotated local records
Reviewed-by: vromero
This commit is contained in:
parent
56d333c538
commit
19c5bfe42f
src/jdk.compiler/share/classes/com/sun/tools/javac/comp
test/langtools/tools/javac/api
@ -995,11 +995,13 @@ public class TypeEnter implements Completer {
|
||||
ClassSymbol sym = tree.sym;
|
||||
ClassType ct = (ClassType)sym.type;
|
||||
|
||||
JCTree defaultConstructor = null;
|
||||
|
||||
// Add default constructor if needed.
|
||||
DefaultConstructorHelper helper = getDefaultConstructorHelper(env);
|
||||
if (helper != null) {
|
||||
JCTree constrDef = defaultConstructor(make.at(tree.pos), helper);
|
||||
tree.defs = tree.defs.prepend(constrDef);
|
||||
defaultConstructor = defaultConstructor(make.at(tree.pos), helper);
|
||||
tree.defs = tree.defs.prepend(defaultConstructor);
|
||||
}
|
||||
if (!sym.isRecord()) {
|
||||
enterThisAndSuper(sym, env);
|
||||
@ -1011,7 +1013,7 @@ public class TypeEnter implements Completer {
|
||||
}
|
||||
}
|
||||
|
||||
finishClass(tree, env);
|
||||
finishClass(tree, defaultConstructor, env);
|
||||
|
||||
if (allowTypeAnnos) {
|
||||
typeAnnotations.organizeTypeAnnotationsSignatures(env, (JCClassDecl)env.tree);
|
||||
@ -1052,7 +1054,7 @@ public class TypeEnter implements Completer {
|
||||
|
||||
/** Enter members for a class.
|
||||
*/
|
||||
void finishClass(JCClassDecl tree, Env<AttrContext> env) {
|
||||
void finishClass(JCClassDecl tree, JCTree defaultConstructor, Env<AttrContext> env) {
|
||||
if ((tree.mods.flags & Flags.ENUM) != 0 &&
|
||||
!tree.sym.type.hasTag(ERROR) &&
|
||||
(types.supertype(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) {
|
||||
@ -1063,9 +1065,7 @@ public class TypeEnter implements Completer {
|
||||
if (isRecord) {
|
||||
alreadyEntered = List.convert(JCTree.class, TreeInfo.recordFields(tree));
|
||||
alreadyEntered = alreadyEntered.prependList(tree.defs.stream()
|
||||
.filter(t -> TreeInfo.isConstructor(t) &&
|
||||
((JCMethodDecl)t).sym != null &&
|
||||
(((JCMethodDecl)t).sym.flags_field & Flags.GENERATEDCONSTR) == 0).collect(List.collector()));
|
||||
.filter(t -> TreeInfo.isConstructor(t) && t != defaultConstructor).collect(List.collector()));
|
||||
}
|
||||
List<JCTree> defsToEnter = isRecord ?
|
||||
tree.defs.diff(alreadyEntered) : tree.defs;
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8205418 8207229 8207230 8230847 8245786
|
||||
* @bug 8205418 8207229 8207230 8230847 8245786 8247334
|
||||
* @summary Test the outcomes from Trees.getScope
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.comp
|
||||
@ -42,6 +42,7 @@ import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.BlockTree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
@ -80,6 +81,7 @@ public class TestGetScopeResult {
|
||||
new TestGetScopeResult().testAnnotationsLazy();
|
||||
new TestGetScopeResult().testCircular();
|
||||
new TestGetScopeResult().testRecord();
|
||||
new TestGetScopeResult().testLocalRecordAnnotation();
|
||||
}
|
||||
|
||||
public void run() throws IOException {
|
||||
@ -562,6 +564,78 @@ public class TestGetScopeResult {
|
||||
}
|
||||
}
|
||||
|
||||
void testLocalRecordAnnotation() throws IOException {
|
||||
JavacTool c = JavacTool.create();
|
||||
try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
|
||||
class Variant {
|
||||
final String code;
|
||||
final List<List<String>> expectedScopeContent;
|
||||
public Variant(String code, List<List<String>> expectedScopeContent) {
|
||||
this.code = code;
|
||||
this.expectedScopeContent = expectedScopeContent;
|
||||
}
|
||||
}
|
||||
Variant[] variants = new Variant[] {
|
||||
new Variant("""
|
||||
class Test {
|
||||
void t() {
|
||||
record R(@Annotation int i) {
|
||||
void stop () {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@interface Annotation {}
|
||||
""",
|
||||
List.of(
|
||||
List.of("super:java.lang.Object", "this:Test"),
|
||||
List.of("super:java.lang.Object", "this:Test")
|
||||
)),
|
||||
new Variant("""
|
||||
record Test(@Annotation int i) {}
|
||||
@interface Annotation {}
|
||||
""",
|
||||
List.of(
|
||||
List.of("i:int", "super:java.lang.Record", "this:Test"),
|
||||
List.of("super:java.lang.Record", "this:Test")
|
||||
))
|
||||
};
|
||||
for (Variant currentVariant : variants) {
|
||||
class MyFileObject extends SimpleJavaFileObject {
|
||||
MyFileObject() {
|
||||
super(URI.create("myfo:///Test.java"), SOURCE);
|
||||
}
|
||||
@Override
|
||||
public String getCharContent(boolean ignoreEncodingErrors) {
|
||||
return currentVariant.code;
|
||||
}
|
||||
}
|
||||
Context ctx = new Context();
|
||||
TestAnalyzer.preRegister(ctx);
|
||||
List<String> options = List.of("--enable-preview",
|
||||
"-source", System.getProperty("java.specification.version"));
|
||||
JavacTask t = (JavacTask) c.getTask(null, fm, null, options, null,
|
||||
List.of(new MyFileObject()), ctx);
|
||||
CompilationUnitTree cut = t.parse().iterator().next();
|
||||
t.analyze();
|
||||
|
||||
List<List<String>> actual = new ArrayList<>();
|
||||
|
||||
new TreePathScanner<Void, Void>() {
|
||||
@Override
|
||||
public Void visitAnnotation(AnnotationTree node, Void p) {
|
||||
Scope scope = Trees.instance(t).getScope(getCurrentPath());
|
||||
actual.add(dumpScope(scope));
|
||||
return super.visitAnnotation(node, p);
|
||||
}
|
||||
}.scan(cut, null);
|
||||
|
||||
if (!currentVariant.expectedScopeContent.equals(actual)) {
|
||||
throw new AssertionError("Unexpected Scope content: " + actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> dumpScope(Scope scope) {
|
||||
List<String> content = new ArrayList<>();
|
||||
while (scope.getEnclosingClass() != null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user