Skip to content

Commit ee9ba74

Browse files
author
Srikanth Adayapalam
committed
8295184: Printing messages with a RecordComponentElement does not include position
Reviewed-by: vromero
1 parent ba2d28e commit ee9ba74

File tree

7 files changed

+223
-16
lines changed

7 files changed

+223
-16
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java

+14-12
Original file line numberDiff line numberDiff line change
@@ -1519,14 +1519,14 @@ public RecordComponent findRecordComponentToRemove(JCVariableDecl var) {
15191519
/* creates a record component if non is related to the given variable and recreates a brand new one
15201520
* in other case
15211521
*/
1522-
public RecordComponent createRecordComponent(RecordComponent existing, JCVariableDecl var, List<JCAnnotation> annotations) {
1522+
public RecordComponent createRecordComponent(RecordComponent existing, JCVariableDecl rcDecl, VarSymbol varSym) {
15231523
RecordComponent rc = null;
15241524
if (existing != null) {
15251525
recordComponents = List.filter(recordComponents, existing);
1526-
recordComponents = recordComponents.append(rc = new RecordComponent(var.sym, existing.originalAnnos, existing.isVarargs));
1526+
recordComponents = recordComponents.append(rc = new RecordComponent(varSym, existing.ast, existing.isVarargs));
15271527
} else {
15281528
// Didn't find the record component: create one.
1529-
recordComponents = recordComponents.append(rc = new RecordComponent(var.sym, annotations));
1529+
recordComponents = recordComponents.append(rc = new RecordComponent(varSym, rcDecl));
15301530
}
15311531
return rc;
15321532
}
@@ -1786,33 +1786,33 @@ public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
17861786
public static class RecordComponent extends VarSymbol implements RecordComponentElement {
17871787
public MethodSymbol accessor;
17881788
public JCTree.JCMethodDecl accessorMeth;
1789-
/* the original annotations applied to the record component
1790-
*/
1791-
private final List<JCAnnotation> originalAnnos;
1789+
17921790
/* if the user happens to erroneously declare two components with the same name, we need a way to differentiate
17931791
* them, the code will fail anyway but we need to keep the information for better error recovery
17941792
*/
17951793
private final int pos;
17961794

17971795
private final boolean isVarargs;
17981796

1797+
private JCVariableDecl ast;
1798+
17991799
/**
18001800
* Construct a record component, given its flags, name, type and owner.
18011801
*/
18021802
public RecordComponent(Name name, Type type, Symbol owner) {
18031803
super(PUBLIC, name, type, owner);
18041804
pos = -1;
1805-
originalAnnos = List.nil();
1805+
ast = null;
18061806
isVarargs = false;
18071807
}
18081808

1809-
public RecordComponent(VarSymbol field, List<JCAnnotation> annotations) {
1810-
this(field, annotations, field.type.hasTag(TypeTag.ARRAY) && ((ArrayType)field.type).isVarargs());
1809+
public RecordComponent(VarSymbol field, JCVariableDecl ast) {
1810+
this(field, ast, field.type.hasTag(TypeTag.ARRAY) && ((ArrayType)field.type).isVarargs());
18111811
}
18121812

1813-
public RecordComponent(VarSymbol field, List<JCAnnotation> annotations, boolean isVarargs) {
1813+
public RecordComponent(VarSymbol field, JCVariableDecl ast, boolean isVarargs) {
18141814
super(PUBLIC, field.name, field.type, field.owner);
1815-
this.originalAnnos = annotations;
1815+
this.ast = ast;
18161816
this.pos = field.pos;
18171817
/* it is better to store the original information for this one, instead of relying
18181818
* on the info in the type of the symbol. This is because on the presence of APs
@@ -1822,7 +1822,9 @@ public RecordComponent(VarSymbol field, List<JCAnnotation> annotations, boolean
18221822
this.isVarargs = isVarargs;
18231823
}
18241824

1825-
public List<JCAnnotation> getOriginalAnnos() { return originalAnnos; }
1825+
public List<JCAnnotation> getOriginalAnnos() { return this.ast == null ? List.nil() : this.ast.mods.annotations; }
1826+
1827+
public JCVariableDecl declarationFor() { return this.ast; }
18261828

18271829
public boolean isVarargs() {
18281830
return isVarargs;

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java

+10
Original file line numberDiff line numberDiff line change
@@ -3006,6 +3006,16 @@ private void validateAnnotation(JCAnnotation a, JCTree declarationTree, Symbol s
30063006
Arrays.stream(getTargetNames(anno.type.tsym)).anyMatch(name -> name == names.RECORD_COMPONENT)
30073007
).collect(List.collector()));
30083008

3009+
JCVariableDecl fieldAST = (JCVariableDecl) declarationTree;
3010+
for (JCAnnotation fieldAnnot : fieldAST.mods.annotations) {
3011+
for (JCAnnotation rcAnnot : rc.declarationFor().mods.annotations) {
3012+
if (rcAnnot.pos == fieldAnnot.pos) {
3013+
rcAnnot.setType(fieldAnnot.type);
3014+
break;
3015+
}
3016+
}
3017+
}
3018+
30093019
/* At this point, we used to carry over any type annotations from the VARDEF to the record component, but
30103020
* that is problematic, since we get here only when *some* annotation is applied to the SE5 (declaration)
30113021
* annotation location, inadvertently failing to carry over the type annotations when the VarDef has no

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -996,10 +996,8 @@ protected void runPhase(Env<AttrContext> env) {
996996

997997
memberEnter.memberEnter(field, env);
998998

999-
sym.createRecordComponent(rc, field,
1000-
field.mods.annotations.isEmpty() ?
1001-
List.nil() :
1002-
new TreeCopier<JCTree>(make.at(field.pos)).copy(field.mods.annotations));
999+
JCVariableDecl rcDecl = new TreeCopier<JCTree>(make.at(field.pos)).copy(field);
1000+
sym.createRecordComponent(rc, rcDecl, field.sym);
10031001
}
10041002

10051003
enterThisAndSuper(sym, env);

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java

+8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.sun.source.tree.Tree;
3131
import com.sun.source.util.TreePath;
3232
import com.sun.tools.javac.code.*;
33+
import com.sun.tools.javac.code.Symbol.RecordComponent;
3334
import com.sun.tools.javac.comp.AttrContext;
3435
import com.sun.tools.javac.comp.Env;
3536
import com.sun.tools.javac.tree.JCTree.*;
@@ -46,6 +47,7 @@
4647
import static com.sun.tools.javac.tree.JCTree.Tag.BLOCK;
4748
import static com.sun.tools.javac.tree.JCTree.Tag.SYNCHRONIZED;
4849

50+
import javax.lang.model.element.ElementKind;
4951
import javax.tools.JavaFileObject;
5052

5153
import java.util.function.Predicate;
@@ -792,6 +794,12 @@ protected boolean checkMatch(JCTree that, Symbol thatSym) {
792794
result = that;
793795
return true;
794796
}
797+
if (this.sym.getKind() == ElementKind.RECORD_COMPONENT) {
798+
if (thatSym != null && thatSym.getKind() == ElementKind.FIELD && (thatSym.flags_field & RECORD) != 0) {
799+
RecordComponent rc = thatSym.enclClass().getRecordComponent((VarSymbol)thatSym);
800+
return checkMatch(rc.declarationFor(), rc);
801+
}
802+
}
795803
return false;
796804
}
797805
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8295184
27+
* @summary Printing messages with a RecordComponentElement does not include position
28+
* @library /tools/lib
29+
* @modules jdk.compiler/com.sun.tools.javac.api
30+
* jdk.compiler/com.sun.tools.javac.main
31+
* @compile TestWarning.java
32+
* @compile ReproducingAP.java
33+
* @run main RecordComponentSourcePositionTest
34+
*/
35+
36+
import java.nio.file.Path;
37+
import java.util.Arrays;
38+
import java.util.List;
39+
40+
import toolbox.JavacTask;
41+
import toolbox.TestRunner;
42+
import toolbox.ToolBox;
43+
import toolbox.Task;
44+
45+
public class RecordComponentSourcePositionTest extends TestRunner {
46+
47+
ToolBox tb;
48+
49+
public RecordComponentSourcePositionTest() {
50+
super(System.err);
51+
tb = new ToolBox();
52+
}
53+
54+
public static void main(String[] args) throws Exception {
55+
RecordComponentSourcePositionTest t = new RecordComponentSourcePositionTest();
56+
t.runTests();
57+
}
58+
59+
@Test
60+
public void testRecordComponentPositionInDiagnostics() throws Exception {
61+
String code = """
62+
@TestWarning(includeAnnotation = true)
63+
public record Test(
64+
@TestWarning(includeAnnotation = true) int first,
65+
@TestWarning int second) {
66+
}
67+
68+
@TestWarning
69+
record Test2() {}
70+
""";
71+
72+
Path curPath = Path.of(".");
73+
74+
List<String> output = new JavacTask(tb)
75+
.sources(code)
76+
.outdir(curPath)
77+
.options("-XDrawDiagnostics", "-processor", "ReproducingAP")
78+
.run()
79+
.writeAll()
80+
.getOutputLines(Task.OutputKind.DIRECT);
81+
82+
List<String> expected = Arrays.asList(
83+
"Test.java:1:1: compiler.warn.proc.messager: Reporting Test with an annotation",
84+
"Test.java:3:9: compiler.warn.proc.messager: Reporting first with an annotation",
85+
"Test.java:4:26: compiler.warn.proc.messager: Reporting second",
86+
"Test.java:8:1: compiler.warn.proc.messager: Reporting Test2",
87+
"4 warnings");
88+
tb.checkEqual(expected, output);
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.util.Set;
25+
26+
import javax.annotation.processing.AbstractProcessor;
27+
import javax.annotation.processing.RoundEnvironment;
28+
import javax.annotation.processing.SupportedSourceVersion;
29+
import javax.lang.model.SourceVersion;
30+
import javax.lang.model.element.TypeElement;
31+
32+
public class ReproducingAP extends AbstractProcessor {
33+
34+
@Override
35+
public Set<String> getSupportedAnnotationTypes() {
36+
return Set.of(TestWarning.class.getName());
37+
}
38+
39+
@Override
40+
public SourceVersion getSupportedSourceVersion() {
41+
return SourceVersion.latest();
42+
}
43+
44+
@Override
45+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
46+
roundEnv.getElementsAnnotatedWith(TestWarning.class).forEach(e -> {
47+
var annotation = e.getAnnotation(TestWarning.class);
48+
if (annotation.includeAnnotation()) {
49+
processingEnv.getMessager().printMessage(
50+
javax.tools.Diagnostic.Kind.WARNING,
51+
"Reporting " + e.getSimpleName() + " with an annotation",
52+
e,
53+
e.getAnnotationMirrors().get(0));
54+
} else {
55+
processingEnv.getMessager().printMessage(
56+
javax.tools.Diagnostic.Kind.WARNING,
57+
"Reporting " + e.getSimpleName(),
58+
e);
59+
}
60+
});
61+
return false;
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.lang.annotation.ElementType;
25+
import java.lang.annotation.Target;
26+
27+
/**
28+
* Direct {@link ReproducingAP} to emit a warning.
29+
*/
30+
@Target({ElementType.TYPE, ElementType.RECORD_COMPONENT})
31+
public @interface TestWarning {
32+
/**
33+
* {@return {@code true} to include the relevant mirror in the warning message}
34+
*/
35+
boolean includeAnnotation() default false;
36+
}

0 commit comments

Comments
 (0)