# HG changeset patch # User darcy # Date 1556754446 25200 # Node ID 67b040623a125057facd2c95518b948af5ababba # Parent a43d6467317d8f1e160f67aadec37919c9d64443 8146726: Improve AbstractProcessor to issue warnings for repeated information Reviewed-by: jjg, smarks, serb, igerasim diff -r a43d6467317d -r 67b040623a12 src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java --- 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 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 arrayToSet(String[] array, - boolean stripModulePrefixes) { + private Set arrayToSet(String[] array, + boolean stripModulePrefixes, + String contentType, + String annotationName) { assert array != null; - Set set = new HashSet<>(array.length); + Set 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); } diff -r a43d6467317d -r 67b040623a12 src/java.compiler/share/classes/javax/annotation/processing/Processor.java --- 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 diff -r a43d6467317d -r 67b040623a12 test/langtools/tools/javac/processing/warnings/TestRepeatedSupportedItems.java --- /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 annotations, + RoundEnvironment roundEnvironment) { + return true; + } +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Baz { +} diff -r a43d6467317d -r 67b040623a12 test/langtools/tools/javac/processing/warnings/au_8.out --- /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 diff -r a43d6467317d -r 67b040623a12 test/langtools/tools/javac/processing/warnings/au_current.out --- /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