changeset 3956:6f91e41163bc jdk-9+156

6388543: improve accuracy of source positions for AnnotationValue param of Messager.printMessage Reviewed-by: jjg
author cushon
date Mon, 06 Feb 2017 17:19:06 -0800
parents 9a966d7c4708
children b5314160b084 f0bc0f34d2cc
files src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java test/tools/javac/processing/messager/6362067/T6362067.out test/tools/javac/processing/messager/6388543/T6388543.java test/tools/javac/processing/messager/6388543/T6388543.out
diffstat 4 files changed, 144 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java	Mon Feb 06 17:51:54 2017 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java	Mon Feb 06 17:19:06 2017 -0800
@@ -288,7 +288,9 @@
                                    List<JCAnnotation> trees) {
         for (Attribute.Compound anno : annos) {
             for (JCAnnotation tree : trees) {
-                JCTree match = matchAnnoToTree(findme, anno, tree);
+                if (tree.type.tsym != anno.type.tsym)
+                    continue;
+                JCTree match = matchAttributeToTree(findme, anno, tree);
                 if (match != null)
                     return match;
             }
@@ -297,15 +299,15 @@
     }
 
     /**
-     * Returns the tree for an annotation given an Attribute to
-     * search (recursively) and its corresponding tree.
+     * Returns the tree for an attribute given an enclosing attribute to
+     * search (recursively) and the enclosing attribute's corresponding tree.
      * Returns null if the tree cannot be found.
      */
-    private JCTree matchAnnoToTree(final Attribute.Compound findme,
-                                   final Attribute attr,
-                                   final JCTree tree) {
+    private JCTree matchAttributeToTree(final Attribute findme,
+                                        final Attribute attr,
+                                        final JCTree tree) {
         if (attr == findme)
-            return (tree.type.tsym == findme.type.tsym) ? tree : null;
+            return tree;
 
         class Vis implements Attribute.Visitor {
             JCTree result = null;
@@ -317,7 +319,7 @@
                 for (Pair<MethodSymbol, Attribute> pair : anno.values) {
                     JCExpression expr = scanForAssign(pair.fst, tree);
                     if (expr != null) {
-                        JCTree match = matchAnnoToTree(findme, pair.snd, expr);
+                        JCTree match = matchAttributeToTree(findme, pair.snd, expr);
                         if (match != null) {
                             result = match;
                             return;
@@ -326,16 +328,19 @@
                 }
             }
             public void visitArray(Attribute.Array array) {
-                if (tree.hasTag(NEWARRAY) &&
-                        types.elemtype(array.type).tsym == findme.type.tsym) {
-                    List<JCExpression> elems = ((JCNewArray) tree).elems;
+                if (tree.hasTag(NEWARRAY)) {
+                    List<JCExpression> elems = ((JCNewArray)tree).elems;
                     for (Attribute value : array.values) {
-                        if (value == findme) {
-                            result = elems.head;
+                        JCTree match = matchAttributeToTree(findme, value, elems.head);
+                        if (match != null) {
+                            result = match;
                             return;
                         }
                         elems = elems.tail;
                     }
+                } else if (array.values.length == 1) {
+                    // the tree may not be a NEWARRAY for single-element array initializers
+                    result = matchAttributeToTree(findme, array.values[0], tree);
                 }
             }
             public void visitEnum(Attribute.Enum e) {
@@ -710,10 +715,15 @@
         if (annoTree == null)
             return elemTreeTop;
 
-        // 6388543: if v != null, we should search within annoTree to find
-        // the tree matching v. For now, we ignore v and return the tree of
-        // the annotation.
-        return new Pair<>(annoTree, elemTreeTop.snd);
+        if (v == null)
+            return new Pair<>(annoTree, elemTreeTop.snd);
+
+        JCTree valueTree = matchAttributeToTree(
+                cast(Attribute.class, v), cast(Attribute.class, a), annoTree);
+        if (valueTree == null)
+            return new Pair<>(annoTree, elemTreeTop.snd);
+
+        return new Pair<>(valueTree, elemTreeTop.snd);
     }
 
     /**
--- a/test/tools/javac/processing/messager/6362067/T6362067.out	Mon Feb 06 17:51:54 2017 -0800
+++ b/test/tools/javac/processing/messager/6362067/T6362067.out	Mon Feb 06 17:19:06 2017 -0800
@@ -1,5 +1,5 @@
 T6362067.java:19:8: compiler.note.proc.messager: note:elem
 T6362067.java:17:1: compiler.note.proc.messager: note:anno
 T6362067.java:18:1: compiler.note.proc.messager: note:anno
-T6362067.java:18:1: compiler.note.proc.messager: note:value
+T6362067.java:18:19: compiler.note.proc.messager: note:value
 - compiler.note.proc.messager: note:nopos
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/messager/6388543/T6388543.java	Mon Feb 06 17:19:06 2017 -0800
@@ -0,0 +1,101 @@
+/*
+ * @test    /nodynamiccopyright/
+ * @bug     6388543
+ * @summary improve accuracy of source positions for AnnotationValue param of Messager.printMessage
+ * @library /tools/javac/lib
+ * @modules jdk.compiler
+ * @build   JavacTestingAbstractProcessor T6388543
+ * @compile/ref=T6388543.out -XDrawDiagnostics -processor T6388543 -proc:only T6388543.java
+ */
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import static javax.tools.Diagnostic.Kind.NOTE;
+
+class Annotated {
+    @A(1)
+    int a1;
+
+    @A(value = 2)
+    int a2;
+
+    @A(value = {3})
+    int a3;
+
+    @A(value = {4, 5})
+    int a4;
+
+    @B(x = @C(x = E.ONE, y = E.TWO), y = @C(x = E.ONE, y = E.TWO))
+    int b;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface A {
+    int[] value() default 0;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface B {
+    C x() default @C;
+
+    C y() default @C;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface C {
+    E x() default E.ONE;
+
+    E y() default E.ONE;
+}
+
+enum E {
+    ONE,
+    TWO
+}
+
+public class T6388543 extends JavacTestingAbstractProcessor {
+    public boolean process(Set<? extends TypeElement> annos, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver()) {
+            return false;
+        }
+        for (Element e : elements.getTypeElement("Annotated").getEnclosedElements()) {
+            for (AnnotationMirror a : e.getAnnotationMirrors()) {
+                for (AnnotationValue v : a.getElementValues().values()) {
+                    printValue(e, a, v);
+                }
+            }
+        }
+        return false;
+    }
+
+    private void printValue(Element e, AnnotationMirror a, AnnotationValue v) {
+        messager.printMessage(NOTE, String.format("note:value %s + %s", a, v), e, a, v);
+        v.accept(
+                new SimpleAnnotationValueVisitor<Void, Void>() {
+                    @Override
+                    public Void visitArray(List<? extends AnnotationValue> values, Void unused) {
+                        for (AnnotationValue value : values) {
+                            printValue(e, a, value);
+                        }
+                        return null;
+                    }
+
+                    @Override
+                    public Void visitAnnotation(AnnotationMirror nestedAnnotation, Void unused) {
+                        for (AnnotationValue value : nestedAnnotation.getElementValues().values()) {
+                            printValue(e, a, value);
+                        }
+                        return null;
+                    }
+                },
+                null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/messager/6388543/T6388543.out	Mon Feb 06 17:19:06 2017 -0800
@@ -0,0 +1,15 @@
+T6388543.java:24:8: compiler.note.proc.messager: note:value @A({1}) + {1}
+T6388543.java:24:8: compiler.note.proc.messager: note:value @A({1}) + 1
+T6388543.java:27:16: compiler.note.proc.messager: note:value @A({2}) + {2}
+T6388543.java:27:16: compiler.note.proc.messager: note:value @A({2}) + 2
+T6388543.java:30:16: compiler.note.proc.messager: note:value @A({3}) + {3}
+T6388543.java:30:17: compiler.note.proc.messager: note:value @A({3}) + 3
+T6388543.java:33:16: compiler.note.proc.messager: note:value @A({4, 5}) + {4, 5}
+T6388543.java:33:17: compiler.note.proc.messager: note:value @A({4, 5}) + 4
+T6388543.java:33:20: compiler.note.proc.messager: note:value @A({4, 5}) + 5
+T6388543.java:36:12: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + @C(x=E.ONE, y=E.TWO)
+T6388543.java:36:20: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + E.ONE
+T6388543.java:36:31: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + E.TWO
+T6388543.java:36:42: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + @C(x=E.ONE, y=E.TWO)
+T6388543.java:36:50: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + E.ONE
+T6388543.java:36:61: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + E.TWO