8146726: Improve AbstractProcessor to issue warnings for repeated information
authordarcy
Wed, 01 May 2019 16:47:26 -0700
changeset 54673 67b040623a12
parent 54672 a43d6467317d
child 54674 27c8a2e0b0e5
8146726: Improve AbstractProcessor to issue warnings for repeated information Reviewed-by: jjg, smarks, serb, igerasim
src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java
src/java.compiler/share/classes/javax/annotation/processing/Processor.java
test/langtools/tools/javac/processing/warnings/TestRepeatedSupportedItems.java
test/langtools/tools/javac/processing/warnings/au_8.out
test/langtools/tools/javac/processing/warnings/au_current.out
--- a/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java	Wed May 01 14:35:28 2019 -0700
+++ b/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java	Wed May 01 16:47:26 2019 -0700
@@ -25,6 +25,7 @@
 
 package javax.annotation.processing;
 
+import java.util.List;
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Collections;
@@ -80,10 +81,9 @@
      */
     public Set<String> getSupportedOptions() {
         SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class);
-        if  (so == null)
-            return Collections.emptySet();
-        else
-            return arrayToSet(so.value(), false);
+        return (so == null) ?
+            Set.of() :
+            arrayToSet(so.value(), false, "option value", "@SupportedOptions");
     }
 
     /**
@@ -110,12 +110,13 @@
                                                              "No SupportedAnnotationTypes annotation " +
                                                              "found on " + this.getClass().getName() +
                                                              ", returning an empty set.");
-                return Collections.emptySet();
+                return Set.of();
             } else {
                 boolean stripModulePrefixes =
                         initialized &&
                         processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_8) <= 0;
-                return arrayToSet(sat.value(), stripModulePrefixes);
+                return arrayToSet(sat.value(), stripModulePrefixes,
+                                  "annotation type", "@SupportedAnnotationTypes");
             }
         }
 
@@ -181,7 +182,7 @@
                                                          AnnotationMirror annotation,
                                                          ExecutableElement member,
                                                          String userText) {
-        return Collections.emptyList();
+        return List.of();
     }
 
     /**
@@ -195,17 +196,33 @@
         return initialized;
     }
 
-    private static Set<String> arrayToSet(String[] array,
-                                          boolean stripModulePrefixes) {
+    private Set<String> arrayToSet(String[] array,
+                                          boolean stripModulePrefixes,
+                                   String contentType,
+                                   String annotationName) {
         assert array != null;
-        Set<String> set = new HashSet<>(array.length);
+        Set<String> set = new HashSet<>();
         for (String s : array) {
+            boolean stripped = false;
             if (stripModulePrefixes) {
                 int index = s.indexOf('/');
-                if (index != -1)
+                if (index != -1) {
                     s = s.substring(index + 1);
+                    stripped = true;
+                }
             }
-            set.add(s);
+            boolean added = set.add(s);
+            // Don't issue a duplicate warning when the module name is
+            // stripped off to avoid spurious warnings in a case like
+            // "foo/a.B", "bar/a.B".
+            if (!added && !stripped && isInitialized() ) {
+                processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
+                                                         "Duplicate " + contentType  +
+                                                         " ``" + s  + "'' for processor " +
+                                                         this.getClass().getName() +
+                                                         " in its " + annotationName  +
+                                                         "annotation.");
+            }
         }
         return Collections.unmodifiableSet(set);
     }
--- a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java	Wed May 01 14:35:28 2019 -0700
+++ b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java	Wed May 01 16:47:26 2019 -0700
@@ -252,7 +252,7 @@
      * "/"} character. For example, if a processor supports {@code
      * "a.B"}, this can include multiple annotation types named {@code
      * a.B} which reside in different modules. To only support {@code
-     * a.B} in the {@code Foo} module, instead use {@code "Foo/a.B"}.
+     * a.B} in the {@code foo} module, instead use {@code "foo/a.B"}.
      *
      * If a module name is included, only an annotation in that module
      * is matched. In particular, if a module name is given in an
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/warnings/TestRepeatedSupportedItems.java	Wed May 01 16:47:26 2019 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8146726
+ * @summary Test that warnings about repeated supported options and annotation types output as expected.
+ * @compile TestRepeatedSupportedItems.java
+ * @compile/ref=au_8.out       -XDrawDiagnostics -processor TestRepeatedSupportedItems -proc:only  -source 8 -Xlint:-options TestRepeatedSupportedItems.java
+ * @compile/ref=au_current.out -XDrawDiagnostics -processor TestRepeatedSupportedItems -proc:only            -Xlint:-options TestRepeatedSupportedItems.java
+ */
+
+import java.lang.annotation.*;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Arrays;
+import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * A warning should be issued by the logic in
+ * javax.annotation.processing.AbstractProcessor for the repeated
+ * information.  The "Foo" option warnings occur regardless of source
+ * level. The number of times the Baz annotation type is repeated
+ * depends on whether or not the source level supports modules.
+ */
+@SupportedAnnotationTypes({"foo/Baz", "foo/Baz", "bar/Baz", "Baz", "Baz"})
+@SupportedOptions({"Foo", "Foo"})
+@Baz
+public class TestRepeatedSupportedItems extends AbstractProcessor {
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    public boolean process(Set<? extends TypeElement> annotations,
+                           RoundEnvironment roundEnvironment) {
+        return true;
+    }
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Baz {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/warnings/au_8.out	Wed May 01 16:47:26 2019 -0700
@@ -0,0 +1,4 @@
+- compiler.warn.proc.messager: Duplicate annotation type ``Baz'' for processor TestRepeatedSupportedItems in its @SupportedAnnotationTypesannotation.
+- compiler.warn.proc.messager: Duplicate annotation type ``Baz'' for processor TestRepeatedSupportedItems in its @SupportedAnnotationTypesannotation.
+- compiler.warn.proc.messager: Duplicate option value ``Foo'' for processor TestRepeatedSupportedItems in its @SupportedOptionsannotation.
+3 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/warnings/au_current.out	Wed May 01 16:47:26 2019 -0700
@@ -0,0 +1,4 @@
+- compiler.warn.proc.messager: Duplicate annotation type ``foo/Baz'' for processor TestRepeatedSupportedItems in its @SupportedAnnotationTypesannotation.
+- compiler.warn.proc.messager: Duplicate annotation type ``Baz'' for processor TestRepeatedSupportedItems in its @SupportedAnnotationTypesannotation.
+- compiler.warn.proc.messager: Duplicate option value ``Foo'' for processor TestRepeatedSupportedItems in its @SupportedOptionsannotation.
+3 warnings