diff options
author | Andrei Onea <andreionea@google.com> | 2019-05-08 13:50:16 +0100 |
---|---|---|
committer | Andrei Onea <andreionea@google.com> | 2019-05-08 18:03:15 +0100 |
commit | 5e226140987c6042679fc8110766959e679105e8 (patch) | |
tree | 823256152e53a1589a9d8383273627cb8e1b154f /tools/processors | |
parent | 5c47b52b93bc84521b8caa9e115ab415ed9f86ac (diff) |
Support all UnsupportedAppUsage annotations in processor
Add support for the libcore UnsupportedAppUsage annotation to
UnsupportedAppUsageProcessor. This is in order to make the two
annotations even more interchangeable.
Also take the opportunity to correct the documentation:
UnsupportedAppUsageProcessor no longer is involved in creating
greylist.txt, that functionality has been moved to
Class2Greylist.java in the art repository.
Bug: 130721457
Test: m framework-annotation-proc
Change-Id: I5cf1f97ca41349fc053315a2fd5bfd53a80ae128
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; } |