diff options
author | Andrei-Valentin Onea <andreionea@google.com> | 2019-05-09 08:46:32 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-05-09 08:46:32 -0700 |
commit | 0c7c762cdc12860729439190dfe889005fa6245a (patch) | |
tree | 052bd2298f41b1f9f6f4d10eb486dc46867a3e29 /tools/processors | |
parent | 50db797d24425c2835aab8dde0b141c9bcf8498d (diff) | |
parent | c3c21f919521ad7a4af0ef25e5249e744dbb313e (diff) |
Merge "Support all UnsupportedAppUsage annotations in processor" am: 3423014cbe
am: c3c21f9195
Change-Id: I595aa4ddbf6f7d7774e17c6d6d88be40e4d59d0d
Diffstat (limited to 'tools/processors')
2 files changed, 81 insertions, 45 deletions
diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java index ef2914610f80..5a5703ed520c 100644 --- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java +++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java @@ -20,12 +20,13 @@ import static javax.lang.model.element.ElementKind.PACKAGE; import static javax.tools.Diagnostic.Kind.ERROR; import static javax.tools.Diagnostic.Kind.WARNING; -import android.annotation.UnsupportedAppUsage; - import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.sun.tools.javac.code.Type; +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -69,6 +70,7 @@ public class SignatureBuilder { public SignatureBuilderException(String message) { super(message); } + public void report(Element offendingElement) { mMessager.printMessage(ERROR, getMessage(), offendingElement); } @@ -153,7 +155,7 @@ public class SignatureBuilder { /** * Get the signature for an executable, either a method or a constructor. * - * @param name "<init>" for constructor, else the method name + * @param name "<init>" for constructor, else the method name * @param method The executable element in question. */ private String getExecutableSignature(CharSequence name, ExecutableElement method) @@ -191,8 +193,13 @@ public class SignatureBuilder { return sig.toString(); } - public String buildSignature(Element element) { - UnsupportedAppUsage uba = element.getAnnotation(UnsupportedAppUsage.class); + /** + * Creates the signature for an annotated element. + * + * @param annotationType type of annotation being processed. + * @param element element for which we want to create a signature. + */ + public String buildSignature(Class<? extends Annotation> annotationType, Element element) { try { String signature; switch (element.getKind()) { @@ -208,18 +215,35 @@ public class SignatureBuilder { default: return null; } - // if we have an expected signature on the annotation, warn if it doesn't match. - if (!Strings.isNullOrEmpty(uba.expectedSignature())) { - if (!signature.equals(uba.expectedSignature())) { - mMessager.printMessage( - WARNING, - String.format("Expected signature doesn't match generated signature.\n" - + " Expected: %s\n Generated: %s", - uba.expectedSignature(), signature), - element); + // Obtain annotation objects + Annotation annotation = element.getAnnotation(annotationType); + if (annotation == null) { + throw new IllegalStateException( + "Element doesn't have any UnsupportedAppUsage annotation"); + } + try { + Method expectedSignatureMethod = annotationType.getMethod("expectedSignature"); + // If we have an expected signature on the annotation, warn if it doesn't match. + String expectedSignature = expectedSignatureMethod.invoke(annotation).toString(); + if (!Strings.isNullOrEmpty(expectedSignature)) { + if (!signature.equals(expectedSignature)) { + mMessager.printMessage( + WARNING, + String.format( + "Expected signature doesn't match generated signature.\n" + + " Expected: %s\n Generated: %s", + expectedSignature, signature), + element); + } } + return signature; + } catch (NoSuchMethodException e) { + throw new IllegalStateException( + "Annotation type does not have expectedSignature parameter", e); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException( + "Could not get expectedSignature parameter for annotation", e); } - return signature; } catch (SignatureBuilderException problem) { problem.report(element); return null; diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java index d368136c7081..5bb956a1fea2 100644 --- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java +++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java @@ -18,9 +18,8 @@ package android.processor.unsupportedappusage; import static javax.tools.StandardLocation.CLASS_OUTPUT; -import android.annotation.UnsupportedAppUsage; - import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; import com.sun.tools.javac.model.JavacElements; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.util.Pair; @@ -28,6 +27,7 @@ import com.sun.tools.javac.util.Position; import java.io.IOException; import java.io.PrintStream; +import java.lang.annotation.Annotation; import java.net.URLEncoder; import java.util.Map; import java.util.Set; @@ -47,14 +47,14 @@ import javax.lang.model.element.TypeElement; /** * Annotation processor for {@link UnsupportedAppUsage} annotations. * - * This processor currently outputs two things: - * 1. A greylist.txt containing dex signatures of all annotated elements. - * 2. A CSV file with a mapping of dex signatures to corresponding source positions. + * This processor currently outputs a CSV file with a mapping of dex signatures to corresponding + * source positions. * - * The first will be used at a later stage of the build to add access flags to the dex file. The - * second is used for automating updates to the annotations themselves. + * This is used for automating updates to the annotations themselves. */ -@SupportedAnnotationTypes({"android.annotation.UnsupportedAppUsage"}) +@SupportedAnnotationTypes({"android.annotation.UnsupportedAppUsage", + "dalvik.annotation.compat.UnsupportedAppUsage" +}) public class UnsupportedAppUsageProcessor extends AbstractProcessor { // Package name for writing output. Output will be written to the "class output" location within @@ -62,6 +62,13 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor { private static final String PACKAGE = "unsupportedappusage"; private static final String INDEX_CSV = "unsupportedappusage_index.csv"; + private static final ImmutableSet<Class<? extends Annotation>> SUPPORTED_ANNOTATIONS = + ImmutableSet.of(android.annotation.UnsupportedAppUsage.class, + dalvik.annotation.compat.UnsupportedAppUsage.class); + private static final ImmutableSet<String> SUPPORTED_ANNOTATION_NAMES = + SUPPORTED_ANNOTATIONS.stream().map(annotation -> annotation.getCanonicalName()).collect( + ImmutableSet.toImmutableSet()); + @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latest(); @@ -92,8 +99,7 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor { private AnnotationMirror getUnsupportedAppUsageAnnotationMirror(Element e) { for (AnnotationMirror m : e.getAnnotationMirrors()) { TypeElement type = (TypeElement) m.getAnnotationType().asElement(); - if (type.getQualifiedName().toString().equals( - UnsupportedAppUsage.class.getCanonicalName())) { + if (SUPPORTED_ANNOTATION_NAMES.contains(type.getQualifiedName().toString())) { return m; } } @@ -133,12 +139,12 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor { /** * Maps an annotated element to the source position of the @UnsupportedAppUsage annotation * attached to it. It returns CSV in the format: - * dex-signature,filename,start-line,start-col,end-line,end-col + * dex-signature,filename,start-line,start-col,end-line,end-col * * The positions refer to the annotation itself, *not* the annotated member. This can therefore * be used to read just the annotation from the file, and to perform in-place edits on it. * - * @param signature the dex signature for the element. + * @param signature the dex signature for the element. * @param annotatedElement The annotated element * @return A single line of CSV text */ @@ -164,28 +170,34 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor { */ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith( - UnsupportedAppUsage.class); - if (annotated.size() == 0) { - return true; - } - // build signatures for each annotated member, and put them in a map of signature to member Map<String, Element> signatureMap = new TreeMap<>(); SignatureBuilder sb = new SignatureBuilder(processingEnv.getMessager()); - for (Element e : annotated) { - String sig = sb.buildSignature(e); - if (sig != null) { - signatureMap.put(sig, e); + for (Class<? extends Annotation> supportedAnnotation : SUPPORTED_ANNOTATIONS) { + Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith( + supportedAnnotation); + if (annotated.size() == 0) { + continue; + } + // Build signatures for each annotated member and put them in a map from signature to + // member. + for (Element e : annotated) { + String sig = sb.buildSignature(supportedAnnotation, e); + if (sig != null) { + signatureMap.put(sig, e); + } } } - try { - writeToFile(INDEX_CSV, - getCsvHeaders(), - signatureMap.entrySet() - .stream() - .map(e -> getAnnotationIndex(e.getKey() ,e.getValue()))); - } catch (IOException e) { - throw new RuntimeException("Failed to write output", e); + + if (!signatureMap.isEmpty()) { + try { + writeToFile(INDEX_CSV, + getCsvHeaders(), + signatureMap.entrySet() + .stream() + .map(e -> getAnnotationIndex(e.getKey(), e.getValue()))); + } catch (IOException e) { + throw new RuntimeException("Failed to write output", e); + } } return true; } |