Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 183f1ccb authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Annotation processor for @InspectableNodeName"

parents 93d5e803 de080eb7
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -784,18 +784,6 @@ java_library {
    ],
}

// A host library containing the inspector annotations for inspector-annotation-processor.
java_library_host {
    name: "inspector-annotation",
    srcs: [
        "core/java/android/view/inspector/InspectableNodeName.java",
        "core/java/android/view/inspector/InspectableProperty.java",
        // Needed for the ResourceId.ID_NULL constant
        "core/java/android/content/res/ResourceId.java",
        "core/java/android/annotation/AnyRes.java",
    ],
}

// A host library including just UnsupportedAppUsage.java so that the annotation
// processor can also use this annotation.
java_library_host {
+27 −0
Original line number Diff line number Diff line
java_library_host {
    name: "view-inspector-annotation-processor",

    srcs: ["src/java/**/*.java"],
    java_resource_dirs: ["src/resources"],

    static_libs: [
    	"javapoet",
    ],

    use_tools_jar: true,
}

java_test_host {
    name: "view-inspector-annotation-processor-test",

    srcs: ["test/java/**/*.java"],
    java_resource_dirs: ["test/resources"],

    static_libs: [
        "guava",
        "junit",
        "view-inspector-annotation-processor",
    ],

    test_suites: ["general-tests"],
}
+7 −0
Original line number Diff line number Diff line
{
  "presubmit": [
    {
      "name": "view-inspector-annotation-processor-test"
    }
  ]
}
+117 −0
Original line number Diff line number Diff line
/*
 * 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.view.inspector;

import java.util.Map;
import java.util.Optional;

import javax.annotation.processing.ProcessingEnvironment;
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.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

/**
 * Utilities for working with {@link AnnotationMirror}.
 */
final class AnnotationUtils {
    private final Elements mElementUtils;
    private final Types mTypeUtils;

    AnnotationUtils(ProcessingEnvironment processingEnv) {
        mElementUtils = processingEnv.getElementUtils();
        mTypeUtils = processingEnv.getTypeUtils();
    }

    /**
     * Get a {@link AnnotationMirror} specified by name from an {@link Element}.
     *
     * @param qualifiedName The fully qualified name of the annotation to search for
     * @param element The element to search for annotations on
     * @return The mirror of the requested annotation
     * @throws ProcessingException If there is not exactly one of the requested annotation.
     */
    AnnotationMirror exactlyOneMirror(String qualifiedName, Element element) {
        final Element targetTypeElment = mElementUtils.getTypeElement(qualifiedName);
        final TypeMirror targetType = targetTypeElment.asType();
        AnnotationMirror result = null;

        for (AnnotationMirror annotation : element.getAnnotationMirrors()) {
            final TypeMirror annotationType = annotation.getAnnotationType().asElement().asType();
            if (mTypeUtils.isSameType(annotationType, targetType)) {
                if (result == null) {
                    result = annotation;
                } else {
                    final String message = String.format(
                            "Element had multiple instances of @%s, expected exactly one",
                            targetTypeElment.getSimpleName());

                    throw new ProcessingException(message, element, annotation);
                }
            }
        }

        if (result == null) {
            final String message = String.format(
                    "Expected an @%s annotation, found none", targetTypeElment.getSimpleName());
            throw new ProcessingException(message, element);
        } else {
            return result;
        }
    }

    /**
     * Extract a string-valued property from an {@link AnnotationMirror}.
     *
     * @param propertyName The name of the requested property
     * @param annotationMirror The mirror to search for the property
     * @return The String value of the annotation or null
     */
    Optional<String> stringProperty(String propertyName, AnnotationMirror annotationMirror) {
        final AnnotationValue value = valueByName(propertyName, annotationMirror);
        if (value != null) {
            return Optional.of((String) value.getValue());
        } else {
            return Optional.empty();
        }
    }


    /**
     * Extract a {@link AnnotationValue} from a mirror by string property name.
     *
     * @param propertyName The name of the property requested property
     * @param annotationMirror
     * @return
     */
    AnnotationValue valueByName(String propertyName, AnnotationMirror annotationMirror) {
        final Map<? extends ExecutableElement, ? extends AnnotationValue> valueMap =
                annotationMirror.getElementValues();

        for (ExecutableElement method : valueMap.keySet()) {
            if (method.getSimpleName().contentEquals(propertyName)) {
                return valueMap.get(method);
            }
        }

        return null;
    }

}
+51 −0
Original line number Diff line number Diff line
/*
 * 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.view.inspector;

import com.squareup.javapoet.ClassName;

import java.util.Optional;

/**
 * Model of an inspectable class derived from annotations.
 *
 * This class does not use any {javax.lang.model} objects to facilitate building models for testing
 * {@link InspectionCompanionGenerator}.
 */
public final class InspectableClassModel {
    private final ClassName mClassName;
    private Optional<String> mNodeName = Optional.empty();

    /**
     * @param className The name of the modeled class
     */
    public InspectableClassModel(ClassName className) {
        mClassName = className;
    }

    public ClassName getClassName() {
        return mClassName;
    }

    public Optional<String> getNodeName() {
        return mNodeName;
    }

    public void setNodeName(Optional<String> nodeName) {
        mNodeName = nodeName;
    }
}
Loading