diff options
8 files changed, 0 insertions, 818 deletions
diff --git a/tools/processors/unsupportedappusage/Android.bp b/tools/processors/unsupportedappusage/Android.bp deleted file mode 100644 index 1e96234543c8..000000000000 --- a/tools/processors/unsupportedappusage/Android.bp +++ /dev/null @@ -1,34 +0,0 @@ - -java_library_host { - name: "unsupportedappusage-annotation-processor-lib", - srcs: [ - "src/**/*.java", - ], - static_libs: [ - "guava", - "unsupportedappusage-annotation" - ], - openjdk9: { - javacflags: [ - "--add-modules=jdk.compiler", - "--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", - "--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", - ], - }, -} - -java_plugin { - name: "unsupportedappusage-annotation-processor", - processor_class: "android.processor.unsupportedappusage.UnsupportedAppUsageProcessor", - - java_resources: [ - "META-INF/**/*", - ], - static_libs: [ - "unsupportedappusage-annotation-processor-lib" - ], - - use_tools_jar: true, -} diff --git a/tools/processors/unsupportedappusage/META-INF/services/javax.annotation.processing.Processor b/tools/processors/unsupportedappusage/META-INF/services/javax.annotation.processing.Processor deleted file mode 100644 index 4a969d319070..000000000000 --- a/tools/processors/unsupportedappusage/META-INF/services/javax.annotation.processing.Processor +++ /dev/null @@ -1 +0,0 @@ -android.processor.unsupportedappusage.UnsupportedAppUsageProcessor diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java deleted file mode 100644 index 65fc733fa364..000000000000 --- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.processor.unsupportedappusage; - -import static javax.lang.model.element.ElementKind.PACKAGE; -import static javax.tools.Diagnostic.Kind.ERROR; -import static javax.tools.Diagnostic.Kind.WARNING; - -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; -import java.util.Map; - -import javax.annotation.processing.Messager; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; - -/** - * Builds a dex signature for a given method or field. - */ -public class SignatureBuilder { - - private static final Map<TypeKind, String> TYPE_MAP = ImmutableMap.<TypeKind, String>builder() - .put(TypeKind.BOOLEAN, "Z") - .put(TypeKind.BYTE, "B") - .put(TypeKind.CHAR, "C") - .put(TypeKind.DOUBLE, "D") - .put(TypeKind.FLOAT, "F") - .put(TypeKind.INT, "I") - .put(TypeKind.LONG, "J") - .put(TypeKind.SHORT, "S") - .put(TypeKind.VOID, "V") - .build(); - - private final Messager mMessager; - - /** - * Exception used internally when we can't build a signature. Whenever this is thrown, an error - * will also be written to the Messager. - */ - private class SignatureBuilderException extends Exception { - public SignatureBuilderException(String message) { - super(message); - } - - public void report(Element offendingElement) { - mMessager.printMessage(ERROR, getMessage(), offendingElement); - } - } - - public SignatureBuilder(Messager messager) { - mMessager = messager; - } - - /** - * Returns a list of enclosing elements for the given element, with the package first, and - * excluding the element itself. - */ - private List<Element> getEnclosingElements(Element e) { - List<Element> enclosing = new ArrayList<>(); - e = e.getEnclosingElement(); // don't include the element itself. - while (e != null) { - enclosing.add(e); - e = e.getEnclosingElement(); - } - Collections.reverse(enclosing); - return enclosing; - } - - /** - * Get the dex signature for a clazz, in format "Lpackage/name/Outer$Inner;" - */ - private String getClassSignature(TypeElement clazz) { - StringBuilder sb = new StringBuilder("L"); - for (Element enclosing : getEnclosingElements(clazz)) { - switch (enclosing.getKind()) { - case MODULE: - // ignore this. - break; - case PACKAGE: - sb.append(((PackageElement) enclosing) - .getQualifiedName() - .toString() - .replace('.', '/')); - sb.append('/'); - break; - default: - sb.append(enclosing.getSimpleName()).append('$'); - break; - } - - } - return sb - .append(clazz.getSimpleName()) - .append(";") - .toString(); - } - - /** - * Returns the type signature for a given type. For primitive types, a single character. - * For classes, the class signature. For arrays, a "[" preceeding the component type. - */ - private String getTypeSignature(TypeMirror type) throws SignatureBuilderException { - String sig = TYPE_MAP.get(type.getKind()); - if (sig != null) { - return sig; - } - switch (type.getKind()) { - case ARRAY: - return "[" + getTypeSignature(((ArrayType) type).getComponentType()); - case DECLARED: - Element declaring = ((DeclaredType) type).asElement(); - if (!(declaring instanceof TypeElement)) { - throw new SignatureBuilderException( - "Can't handle declared type of kind " + declaring.getKind()); - } - return getClassSignature((TypeElement) declaring); - case TYPEVAR: - Type.TypeVar typeVar = (Type.TypeVar) type; - if (typeVar.getLowerBound().getKind() != TypeKind.NULL) { - return getTypeSignature(typeVar.getLowerBound()); - } else if (typeVar.getUpperBound().getKind() != TypeKind.NULL) { - return getTypeSignature(typeVar.getUpperBound()); - } else { - throw new SignatureBuilderException("Can't handle typevar with no bound"); - } - - default: - throw new SignatureBuilderException("Can't handle type of kind " + type.getKind()); - } - } - - /** - * Get the signature for an executable, either a method or a constructor. - * - * @param name "<init>" for constructor, else the method name - * @param method The executable element in question. - */ - private String getExecutableSignature(CharSequence name, ExecutableElement method) - throws SignatureBuilderException { - StringBuilder sig = new StringBuilder(); - sig.append(getClassSignature((TypeElement) method.getEnclosingElement())) - .append("->") - .append(name) - .append("("); - for (VariableElement param : method.getParameters()) { - sig.append(getTypeSignature(param.asType())); - } - sig.append(")") - .append(getTypeSignature(method.getReturnType())); - return sig.toString(); - } - - private String buildMethodSignature(ExecutableElement method) throws SignatureBuilderException { - return getExecutableSignature(method.getSimpleName(), method); - } - - private String buildConstructorSignature(ExecutableElement cons) - throws SignatureBuilderException { - return getExecutableSignature("<init>", cons); - } - - private String buildFieldSignature(VariableElement field) throws SignatureBuilderException { - StringBuilder sig = new StringBuilder(); - sig.append(getClassSignature((TypeElement) field.getEnclosingElement())) - .append("->") - .append(field.getSimpleName()) - .append(":") - .append(getTypeSignature(field.asType())) - ; - return sig.toString(); - } - - /** - * 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()) { - case METHOD: - signature = buildMethodSignature((ExecutableElement) element); - break; - case CONSTRUCTOR: - signature = buildConstructorSignature((ExecutableElement) element); - break; - case FIELD: - signature = buildFieldSignature((VariableElement) element); - break; - default: - return null; - } - // 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); - } - } catch (SignatureBuilderException problem) { - problem.report(element); - return null; - } - } -} diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SourcePosition.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SourcePosition.java deleted file mode 100644 index 4ae093c3c2e4..000000000000 --- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SourcePosition.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.processor.unsupportedappusage; - -/** - * Represents a source position within a source file - */ -public class SourcePosition { - public final String filename; - public final int startLine; - public final int startCol; - public final int endLine; - public final int endCol; - - public SourcePosition(String filename, int startLine, int startCol, int endLine, int endCol) { - this.filename = filename; - this.startLine = startLine; - this.startCol = startCol; - this.endLine = endLine; - this.endCol = endCol; - } -} diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java deleted file mode 100644 index ca2c2759d702..000000000000 --- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.processor.unsupportedappusage; - -import static javax.tools.StandardLocation.CLASS_OUTPUT; - -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; -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; -import java.util.TreeMap; -import java.util.stream.Stream; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; - -/** - * Annotation processor for {@link UnsupportedAppUsage} annotations. - * - * This processor currently outputs a CSV file with a mapping of dex signatures to corresponding - * source positions. - * - * This is used for automating updates to the annotations themselves. - */ -@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 - // this package. - 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()); - private static final String OVERRIDE_SOURCE_POSITION_PROPERTY = "overrideSourcePosition"; - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latest(); - } - - /** - * Write the contents of a stream to a text file, with one line per item. - */ - private void writeToFile(String name, - String headerLine, - Stream<?> contents) throws IOException { - PrintStream out = new PrintStream(processingEnv.getFiler().createResource( - CLASS_OUTPUT, - PACKAGE, - name) - .openOutputStream()); - out.println(headerLine); - contents.forEach(o -> out.println(o)); - if (out.checkError()) { - throw new IOException("Error when writing to " + name); - } - out.close(); - } - - /** - * Find the annotation mirror for the @UnsupportedAppUsage annotation on the given element. - */ - private AnnotationMirror getUnsupportedAppUsageAnnotationMirror(Element e) { - for (AnnotationMirror m : e.getAnnotationMirrors()) { - TypeElement type = (TypeElement) m.getAnnotationType().asElement(); - if (SUPPORTED_ANNOTATION_NAMES.contains(type.getQualifiedName().toString())) { - return m; - } - } - return null; - } - - /** - * Returns a CSV header line for the columns returned by - * {@link #getAnnotationIndex(String, Element)}. - */ - private String getCsvHeaders() { - return Joiner.on(',').join( - "signature", - "file", - "startline", - "startcol", - "endline", - "endcol", - "properties" - ); - } - - private String encodeAnnotationProperties(AnnotationMirror annotation) { - StringBuilder sb = new StringBuilder(); - for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e - : annotation.getElementValues().entrySet()) { - if (e.getKey().getSimpleName().toString().equals(OVERRIDE_SOURCE_POSITION_PROPERTY)) { - continue; - } - if (sb.length() > 0) { - sb.append("&"); - } - sb.append(e.getKey().getSimpleName()) - .append("=") - .append(URLEncoder.encode(e.getValue().toString())); - } - return sb.toString(); - } - - private SourcePosition getSourcePositionOverride( - Element annotatedElement, AnnotationMirror annotation) { - for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e - : annotation.getElementValues().entrySet()) { - if (e.getKey().getSimpleName().toString().equals(OVERRIDE_SOURCE_POSITION_PROPERTY)) { - String[] position = e.getValue().getValue().toString().split(":"); - if (position.length != 5) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, String.format( - "Expected %s to have format file:startLine:startCol:endLine:endCol", - OVERRIDE_SOURCE_POSITION_PROPERTY), annotatedElement, annotation); - return null; - } - try { - return new SourcePosition(position[0], Integer.parseInt(position[1]), - Integer.parseInt(position[2]), Integer.parseInt(position[3]), - Integer.parseInt(position[4])); - } catch (NumberFormatException nfe) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, String.format( - "Expected %s to have format file:startLine:startCol:endLine:endCol; " - + "error parsing integer: %s", OVERRIDE_SOURCE_POSITION_PROPERTY, - nfe.getMessage()), annotatedElement, annotation); - return null; - } - } - } - return null; - } - - /** - * 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 - * - * 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 annotatedElement The annotated element - * @return A single line of CSV text - */ - private String getAnnotationIndex(String signature, Element annotatedElement) { - JavacElements javacElem = (JavacElements) processingEnv.getElementUtils(); - AnnotationMirror unsupportedAppUsage = - getUnsupportedAppUsageAnnotationMirror(annotatedElement); - SourcePosition position = getSourcePositionOverride(annotatedElement, unsupportedAppUsage); - if (position == null) { - Pair<JCTree, JCTree.JCCompilationUnit> pair = - javacElem.getTreeAndTopLevel(annotatedElement, unsupportedAppUsage, null); - Position.LineMap lines = pair.snd.lineMap; - position = new SourcePosition( - pair.snd.getSourceFile().getName(), - lines.getLineNumber(pair.fst.pos().getStartPosition()), - lines.getColumnNumber(pair.fst.pos().getStartPosition()), - lines.getLineNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)), - lines.getColumnNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions))); - } - return Joiner.on(",").join( - signature, - position.filename, - position.startLine, - position.startCol, - position.endLine, - position.endCol, - encodeAnnotationProperties(unsupportedAppUsage)); - } - - /** - * This is the main entry point in the processor, called by the compiler. - */ - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - Map<String, Element> signatureMap = new TreeMap<>(); - SignatureBuilder sb = new SignatureBuilder(processingEnv.getMessager()); - 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); - } - } - } - - 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; - } -} diff --git a/tools/processors/unsupportedappusage/test/Android.bp b/tools/processors/unsupportedappusage/test/Android.bp deleted file mode 100644 index e10fd47e8db1..000000000000 --- a/tools/processors/unsupportedappusage/test/Android.bp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_test_host { - name: "unsupportedappusage-processor-test", - - srcs: ["src/**/*.java"], - - static_libs: [ - "compile-testing-prebuilt", - "unsupportedappusage-annotation-processor-lib", - "truth-host-prebuilt", - "mockito-host", - "junit-host", - "objenesis", - ], -} diff --git a/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java deleted file mode 100644 index 23db99e81194..000000000000 --- a/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/CsvReader.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.processor.unsupportedappusage; - -import com.google.common.base.Splitter; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class CsvReader { - - private final Splitter mSplitter; - private final List<String> mColumns; - private final List<Map<String, String>> mContents; - - public CsvReader(InputStream in) throws IOException { - mSplitter = Splitter.on(","); - BufferedReader br = new BufferedReader(new InputStreamReader(in)); - mColumns = mSplitter.splitToList(br.readLine()); - mContents = new ArrayList<>(); - String line = br.readLine(); - while (line != null) { - List<String> contents = mSplitter.splitToList(line); - Map<String, String> contentMap = new HashMap<>(); - for (int i = 0; i < Math.min(contents.size(), mColumns.size()); ++i) { - contentMap.put(mColumns.get(i), contents.get(i)); - } - mContents.add(contentMap); - line = br.readLine(); - } - br.close(); - } - - public List<String> getColumns() { - return mColumns; - } - - public List<Map<String, String>> getContents() { - return mContents; - } -} diff --git a/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java b/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java deleted file mode 100644 index 75158eebdfdd..000000000000 --- a/tools/processors/unsupportedappusage/test/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessorTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.processor.unsupportedappusage; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.testing.compile.Compilation; -import com.google.testing.compile.CompilationSubject; -import com.google.testing.compile.Compiler; -import com.google.testing.compile.JavaFileObjects; - -import org.junit.Test; - -import java.io.IOException; -import java.util.Map; -import java.util.Optional; - -import javax.tools.JavaFileObject; -import javax.tools.StandardLocation; - -public class UnsupportedAppUsageProcessorTest { - - private static final JavaFileObject ANNOTATION = JavaFileObjects.forSourceLines( - "dalvik.dalvik.annotation.compat.UnsupportedAppUsage", - "package dalvik.annotation.compat;", - "public @interface UnsupportedAppUsage {", - " String expectedSignature() default \"\";\n", - " String someProperty() default \"\";", - " String overrideSourcePosition() default \"\";", - "}"); - - private CsvReader compileAndReadCsv(JavaFileObject source) throws IOException { - Compilation compilation = - Compiler.javac().withProcessors(new UnsupportedAppUsageProcessor()) - .compile(ANNOTATION, source); - CompilationSubject.assertThat(compilation).succeeded(); - Optional<JavaFileObject> csv = compilation.generatedFile(StandardLocation.CLASS_OUTPUT, - "unsupportedappusage/unsupportedappusage_index.csv"); - assertThat(csv.isPresent()).isTrue(); - - return new CsvReader(csv.get().openInputStream()); - } - - @Test - public void testSignatureFormat() throws Exception { - JavaFileObject src = JavaFileObjects.forSourceLines("a.b.Class", - "package a.b;", - "import dalvik.annotation.compat.UnsupportedAppUsage;", - "public class Class {", - " @UnsupportedAppUsage", - " public void method() {}", - "}"); - assertThat(compileAndReadCsv(src).getContents().get(0)).containsEntry( - "signature", "La/b/Class;->method()V" - ); - } - - @Test - public void testSourcePosition() throws Exception { - JavaFileObject src = JavaFileObjects.forSourceLines("a.b.Class", - "package a.b;", // 1 - "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 - "public class Class {", // 3 - " @UnsupportedAppUsage", // 4 - " public void method() {}", // 5 - "}"); - Map<String, String> row = compileAndReadCsv(src).getContents().get(0); - assertThat(row).containsEntry("startline", "4"); - assertThat(row).containsEntry("startcol", "3"); - assertThat(row).containsEntry("endline", "4"); - assertThat(row).containsEntry("endcol", "23"); - } - - @Test - public void testAnnotationProperties() throws Exception { - JavaFileObject src = JavaFileObjects.forSourceLines("a.b.Class", - "package a.b;", // 1 - "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 - "public class Class {", // 3 - " @UnsupportedAppUsage(someProperty=\"value\")", // 4 - " public void method() {}", // 5 - "}"); - assertThat(compileAndReadCsv(src).getContents().get(0)).containsEntry( - "properties", "someProperty=%22value%22"); - } - - @Test - public void testSourcePositionOverride() throws Exception { - JavaFileObject src = JavaFileObjects.forSourceLines("a.b.Class", - "package a.b;", // 1 - "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 - "public class Class {", // 3 - " @UnsupportedAppUsage(overrideSourcePosition=\"otherfile.aidl:30:10:31:20\")", - " public void method() {}", // 5 - "}"); - Map<String, String> row = compileAndReadCsv(src).getContents().get(0); - assertThat(row).containsEntry("file", "otherfile.aidl"); - assertThat(row).containsEntry("startline", "30"); - assertThat(row).containsEntry("startcol", "10"); - assertThat(row).containsEntry("endline", "31"); - assertThat(row).containsEntry("endcol", "20"); - assertThat(row).containsEntry("properties", ""); - } - - @Test - public void testSourcePositionOverrideWrongFormat() throws Exception { - JavaFileObject src = JavaFileObjects.forSourceLines("a.b.Class", - "package a.b;", // 1 - "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 - "public class Class {", // 3 - " @UnsupportedAppUsage(overrideSourcePosition=\"invalid\")", // 4 - " public void method() {}", // 5 - "}"); - Compilation compilation = - Compiler.javac().withProcessors(new UnsupportedAppUsageProcessor()) - .compile(ANNOTATION, src); - CompilationSubject.assertThat(compilation).failed(); - CompilationSubject.assertThat(compilation).hadErrorContaining( - "Expected overrideSourcePosition to have format " - + "file:startLine:startCol:endLine:endCol").inFile(src).onLine(4); - } - - @Test - public void testSourcePositionOverrideInvalidInt() throws Exception { - JavaFileObject src = JavaFileObjects.forSourceLines("a.b.Class", - "package a.b;", // 1 - "import dalvik.annotation.compat.UnsupportedAppUsage;", // 2 - "public class Class {", // 3 - " @UnsupportedAppUsage(overrideSourcePosition=\"otherfile.aidl:a:b:c:d\")", // 4 - " public void method() {}", // 5 - "}"); - Compilation compilation = - Compiler.javac().withProcessors(new UnsupportedAppUsageProcessor()) - .compile(ANNOTATION, src); - CompilationSubject.assertThat(compilation).failed(); - CompilationSubject.assertThat(compilation).hadErrorContaining( - "error parsing integer").inFile(src).onLine(4); - } - -} |