diff options
author | Ashley Rose <ashleyrose@google.com> | 2019-03-13 18:15:44 -0400 |
---|---|---|
committer | Ashley Rose <ashleyrose@google.com> | 2019-03-15 15:47:53 -0400 |
commit | 83bac9f33a064baef9f1755942b623c7764a9950 (patch) | |
tree | 739f17a465ce724c0261286bf4bd713846c6bf57 | |
parent | 0a6dc7537157949ec6b09a18fdab5d32f1c1692c (diff) |
Use IntFunction for inspector flag and enum mapping
+ Remove IntEnumMapping class, (use a bound lambda of
SparseArray#get(int) instead).
+ Remove IntFlagMapping.Builder, and make IntFlagMapping mutable. The
immuability guarantees are provided by using a lambda of
IntFlagMapping#get(int).
+ Change PropertyMapper#mapIntEnum(String, int, IntFunction<String>)
and #mapIntFlag(String, int, IntFunction<Set<String>>) to take
IntFunctions instead of semantic types.
+ Changes to the annotation processor to support code generation for the
lambdas and additional internal cleanups.
Bug: 124448834
Test: atest --host view-inspector-annotation-processor-test
Change-Id: I3e7ccac63d50caa6ff49be1e78732831886e7f6e
22 files changed, 500 insertions, 553 deletions
diff --git a/api/current.txt b/api/current.txt index 0176c68b6295..ef3c6ca55296 100644 --- a/api/current.txt +++ b/api/current.txt @@ -53478,27 +53478,12 @@ package android.view.inspector { method @Nullable public <T> android.view.inspector.InspectionCompanion<T> provide(@NonNull Class<T>); } - public final class IntEnumMapping { - method @Nullable public String get(int); - } - - public static final class IntEnumMapping.Builder { - ctor public IntEnumMapping.Builder(); - method @NonNull public android.view.inspector.IntEnumMapping.Builder addValue(@NonNull String, int); - method @NonNull public android.view.inspector.IntEnumMapping build(); - } - public final class IntFlagMapping { + ctor public IntFlagMapping(); + method public void add(int, int, @NonNull String); method @NonNull public java.util.Set<java.lang.String> get(int); } - public static final class IntFlagMapping.Builder { - ctor public IntFlagMapping.Builder(); - method @NonNull public android.view.inspector.IntFlagMapping.Builder addFlag(@NonNull String, int); - method @NonNull public android.view.inspector.IntFlagMapping.Builder addFlag(@NonNull String, int, int); - method @NonNull public android.view.inspector.IntFlagMapping build(); - } - public interface PropertyMapper { method public int mapBoolean(@NonNull String, @AttrRes int); method public int mapByte(@NonNull String, @AttrRes int); @@ -53508,8 +53493,8 @@ package android.view.inspector { method public int mapFloat(@NonNull String, @AttrRes int); method public int mapGravity(@NonNull String, @AttrRes int); method public int mapInt(@NonNull String, @AttrRes int); - method public int mapIntEnum(@NonNull String, @AttrRes int, @NonNull android.view.inspector.IntEnumMapping); - method public int mapIntFlag(@NonNull String, @AttrRes int, @NonNull android.view.inspector.IntFlagMapping); + method public int mapIntEnum(@NonNull String, @AttrRes int, @NonNull java.util.function.IntFunction<java.lang.String>); + method public int mapIntFlag(@NonNull String, @AttrRes int, @NonNull java.util.function.IntFunction<java.util.Set<java.lang.String>>); method public int mapLong(@NonNull String, @AttrRes int); method public int mapObject(@NonNull String, @AttrRes int); method public int mapResourceId(@NonNull String, @AttrRes int); diff --git a/core/java/android/view/inspector/IntEnumMapping.java b/core/java/android/view/inspector/IntEnumMapping.java deleted file mode 100644 index 147bb46f2aa4..000000000000 --- a/core/java/android/view/inspector/IntEnumMapping.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 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.view.inspector; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.util.SparseArray; - -import java.util.Objects; - -/** - * Maps the values of an {@code int} property to strings for properties that encode an enumeration. - * - * An {@link InspectionCompanion} may provide an instance of this class to a {@link PropertyMapper} - * for flag values packed into primitive {@code int} properties. - * - * This class is an immutable wrapper for {@link SparseArray}, and must be constructed by a - * {@link Builder}. - * - * @see PropertyMapper#mapIntEnum(String, int, IntEnumMapping) - */ -public final class IntEnumMapping { - private final SparseArray<String> mValues; - - /** - * Get the name for the given property value - * - * @param value The value of the property - * @return The name of the value in the enumeration, or null if no value is defined - */ - @Nullable - public String get(int value) { - return mValues.get(value); - } - - /** - * Create a new instance from a builder. - * - * This constructor is private, use {@link Builder#build()} instead. - * - * @param builder A builder to create from - */ - private IntEnumMapping(Builder builder) { - mValues = builder.mValues.clone(); - } - - /** - * A builder for {@link IntEnumMapping}. - */ - public static final class Builder { - @NonNull - private SparseArray<String> mValues; - private boolean mMustCloneValues = false; - - public Builder() { - mValues = new SparseArray<>(); - } - - /** - * Add a new enumerated value. - * - * @param name The string name of the enumeration value - * @param value The {@code int} value of the enumeration value - * @return This builder - */ - @NonNull - public Builder addValue(@NonNull String name, int value) { - // Save an allocation, only re-clone if the builder is used again after building - if (mMustCloneValues) { - mValues = mValues.clone(); - } - - mValues.put(value, Objects.requireNonNull(name)); - return this; - } - - /** - * Build a new {@link IntEnumMapping} from this builder. - * - * @return A new mapping - */ - @NonNull - public IntEnumMapping build() { - mMustCloneValues = true; - return new IntEnumMapping(this); - } - } -} diff --git a/core/java/android/view/inspector/IntFlagMapping.java b/core/java/android/view/inspector/IntFlagMapping.java index 2409081ca3a5..f50132969064 100644 --- a/core/java/android/view/inspector/IntFlagMapping.java +++ b/core/java/android/view/inspector/IntFlagMapping.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -35,22 +36,20 @@ import java.util.Set; * it by bitwise anding it with the mask and comparing the result against the target, that is, * {@code (value & mask) == target}. * - * This class is immutable, and must be constructed by a {@link Builder}. - * - * @see PropertyMapper#mapIntFlag(String, int, IntFlagMapping) + * @see PropertyMapper#mapIntFlag(String, int, java.util.function.IntFunction) */ public final class IntFlagMapping { - private final Flag[] mFlags; + private final List<Flag> mFlags = new ArrayList<>(); /** - * Get an array of the names of enabled flags for a given property value. + * Get a set of the names of enabled flags for a given property value. * * @param value The value of the property * @return The names of the enabled flags, empty if no flags enabled */ @NonNull public Set<String> get(int value) { - final Set<String> enabledFlagNames = new HashSet<>(mFlags.length); + final Set<String> enabledFlagNames = new HashSet<>(mFlags.size()); for (Flag flag : mFlags) { if (flag.isEnabledFor(value)) { @@ -62,70 +61,14 @@ public final class IntFlagMapping { } /** - * Create a new instance from a builder. - * - * This constructor is private, use {@link Builder#build()} instead. + * Add a mutually exclusive flag to the map. * - * @param builder A builder to create from + * @param mask The bit mask to compare to and with a value + * @param target The target value to compare the masked value with + * @param name The name of the flag to include if enabled */ - private IntFlagMapping(Builder builder) { - mFlags = builder.mFlags.toArray(new Flag[builder.mFlags.size()]); - } - - /** - * A builder for {@link IntFlagMapping}. - */ - public static final class Builder { - private ArrayList<Flag> mFlags; - - public Builder() { - mFlags = new ArrayList<>(); - } - - /** - * Add a new flag without a mask. - * - * The target value will be used as a mask, to handle the common case where flag values - * are not mutually exclusive. The flag will be considered enabled for a property value if - * the result of bitwise anding the target and the value equals the target, that is: - * {@code (value & target) == target}. - * - * @param name The name of the flag - * @param target The value to compare against - * @return This builder - */ - @NonNull - public Builder addFlag(@NonNull String name, int target) { - mFlags.add(new Flag(name, target, target)); - return this; - } - - /** - * Add a new flag with a mask. - * - * The flag will be considered enabled for a property value if the result of bitwise anding - * the value and the mask equals the target, that is: {@code (value & mask) == target}. - * - * @param name The name of the flag - * @param target The value to compare against - * @param mask A bit mask - * @return This builder - */ - @NonNull - public Builder addFlag(@NonNull String name, int target, int mask) { - mFlags.add(new Flag(name, target, mask)); - return this; - } - - /** - * Build a new {@link IntFlagMapping} from this builder. - * - * @return A new mapping - */ - @NonNull - public IntFlagMapping build() { - return new IntFlagMapping(this); - } + public void add(int mask, int target, @NonNull String name) { + mFlags.add(new Flag(mask, target, name)); } /** @@ -136,10 +79,10 @@ public final class IntFlagMapping { private final int mTarget; private final int mMask; - private Flag(@NonNull String name, int target, int mask) { - mName = Objects.requireNonNull(name); + private Flag(int mask, int target, @NonNull String name) { mTarget = target; mMask = mask; + mName = Objects.requireNonNull(name); } /** diff --git a/core/java/android/view/inspector/PropertyMapper.java b/core/java/android/view/inspector/PropertyMapper.java index 54d99df843a1..cbc690eed3a9 100644 --- a/core/java/android/view/inspector/PropertyMapper.java +++ b/core/java/android/view/inspector/PropertyMapper.java @@ -19,6 +19,9 @@ package android.view.inspector; import android.annotation.AttrRes; import android.annotation.NonNull; +import java.util.Set; +import java.util.function.IntFunction; + /** * An interface for mapping the string names of inspectable properties to integer identifiers. * @@ -154,7 +157,7 @@ public interface PropertyMapper { int mapIntEnum( @NonNull String name, @AttrRes int attributeId, - @NonNull IntEnumMapping mapping); + @NonNull IntFunction<String> mapping); /** * Map a string name to an integer ID for an attribute that contains resource IDs. @@ -178,7 +181,7 @@ public interface PropertyMapper { int mapIntFlag( @NonNull String name, @AttrRes int attributeId, - @NonNull IntFlagMapping mapping); + @NonNull IntFunction<Set<String>> mapping); /** * Thrown from a map method if a property name is already mapped as different type. */ diff --git a/tools/processors/view_inspector/Android.bp b/tools/processors/view_inspector/Android.bp index 06ff05e5d755..069e61f5b921 100644 --- a/tools/processors/view_inspector/Android.bp +++ b/tools/processors/view_inspector/Android.bp @@ -8,6 +8,7 @@ java_plugin { static_libs: [ "javapoet", + "stub-annotations", ], use_tools_jar: true, diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java index 2690ee87f5b2..c833e477e265 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java @@ -16,6 +16,8 @@ package android.processor.view.inspector; +import androidx.annotation.NonNull; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -40,7 +42,7 @@ final class AnnotationUtils { private final Elements mElementUtils; private final Types mTypeUtils; - AnnotationUtils(ProcessingEnvironment processingEnv) { + AnnotationUtils(@NonNull ProcessingEnvironment processingEnv) { mElementUtils = processingEnv.getElementUtils(); mTypeUtils = processingEnv.getTypeUtils(); } @@ -53,7 +55,8 @@ final class AnnotationUtils { * @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) { + @NonNull + AnnotationMirror exactlyOneMirror(@NonNull String qualifiedName, @NonNull Element element) { final Element targetTypeElment = mElementUtils.getTypeElement(qualifiedName); final TypeMirror targetType = targetTypeElment.asType(); AnnotationMirror result = null; @@ -89,7 +92,7 @@ final class AnnotationUtils { * @param annotationQualifiedName The name of the annotation to check for * @return True if the annotation is present, false otherwise */ - boolean hasAnnotation(Element element, String annotationQualifiedName) { + boolean hasAnnotation(@NonNull Element element, @NonNull String annotationQualifiedName) { final TypeElement namedElement = mElementUtils.getTypeElement(annotationQualifiedName); if (namedElement != null) { @@ -118,10 +121,10 @@ final class AnnotationUtils { * @return A list containing the requested types */ <T> List<T> typedArrayValuesByName( - String propertyName, - Class<T> valueClass, - Element element, - AnnotationMirror annotationMirror) { + @NonNull String propertyName, + @NonNull Class<T> valueClass, + @NonNull Element element, + @NonNull AnnotationMirror annotationMirror) { return untypedArrayValuesByName(propertyName, element, annotationMirror) .stream() .map(annotationValue -> { @@ -159,10 +162,11 @@ final class AnnotationUtils { * @param annotationMirror An annotation mirror to search for the property * @return A list of annotation values, empty list if none found */ + @NonNull List<AnnotationValue> untypedArrayValuesByName( - String propertyName, - Element element, - AnnotationMirror annotationMirror) { + @NonNull String propertyName, + @NonNull Element element, + @NonNull AnnotationMirror annotationMirror) { return typedValueByName(propertyName, List.class, element, annotationMirror) .map(untypedValues -> { List<AnnotationValue> typedValues = new ArrayList<>(untypedValues.size()); @@ -195,6 +199,7 @@ final class AnnotationUtils { * @param <T> The type of the value * @return An optional containing the typed value of the named property */ + @NonNull <T> Optional<T> typedValueByName( String propertyName, Class<T> valueClass, @@ -241,10 +246,11 @@ final class AnnotationUtils { * @return An optional containing the untyped value of the named property * @see AnnotationValue#getValue() */ + @NonNull Optional<Object> untypedValueByName( - String propertyName, - Element element, - AnnotationMirror annotationMirror) { + @NonNull String propertyName, + @NonNull Element element, + @NonNull AnnotationMirror annotationMirror) { return valueByName(propertyName, annotationMirror).map(annotationValue -> { final Object value = annotationValue.getValue(); @@ -269,7 +275,10 @@ final class AnnotationUtils { * @param annotationMirror The mirror to search for the property * @return The value of the property */ - Optional<AnnotationValue> valueByName(String propertyName, AnnotationMirror annotationMirror) { + @NonNull + Optional<AnnotationValue> valueByName( + @NonNull String propertyName, + @NonNull AnnotationMirror annotationMirror) { final Map<? extends ExecutableElement, ? extends AnnotationValue> valueMap = annotationMirror.getElementValues(); diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java index 1ad7ada95018..147f054b1abb 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java @@ -16,6 +16,9 @@ package android.processor.view.inspector; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.squareup.javapoet.ClassName; import java.util.Collection; @@ -34,27 +37,29 @@ import java.util.Optional; * testing {@link InspectionCompanionGenerator}. */ public final class InspectableClassModel { - private final ClassName mClassName; - private final Map<String, Property> mPropertyMap; - private Optional<String> mNodeName = Optional.empty(); + private final @NonNull ClassName mClassName; + private final @NonNull Map<String, Property> mPropertyMap; + private @NonNull Optional<String> mNodeName = Optional.empty(); /** * @param className The name of the modeled class */ - public InspectableClassModel(ClassName className) { + public InspectableClassModel(@NonNull ClassName className) { mClassName = className; mPropertyMap = new HashMap<>(); } + @NonNull public ClassName getClassName() { return mClassName; } + @NonNull public Optional<String> getNodeName() { return mNodeName; } - public void setNodeName(Optional<String> nodeName) { + public void setNodeName(@NonNull Optional<String> nodeName) { mNodeName = nodeName; } @@ -63,7 +68,7 @@ public final class InspectableClassModel { * * @param property The property to add or replace */ - public void putProperty(Property property) { + public void putProperty(@NonNull Property property) { mPropertyMap.put(property.getName(), property); } @@ -73,7 +78,8 @@ public final class InspectableClassModel { * @param name The name of the property * @return The property or an empty optional */ - public Optional<Property> getProperty(String name) { + @NonNull + public Optional<Property> getProperty(@NonNull String name) { return Optional.ofNullable(mPropertyMap.get(name)); } @@ -82,6 +88,7 @@ public final class InspectableClassModel { * * @return An un-ordered collection of properties */ + @NonNull public Collection<Property> getAllProperties() { return mPropertyMap.values(); } @@ -90,8 +97,8 @@ public final class InspectableClassModel { * Represents a way to access a property, either a getter or a field. */ public static final class Accessor { - private final String mName; - private final Type mType; + private final @NonNull String mName; + private final @NonNull Type mType; /** * Construct an accessor for a field. @@ -100,7 +107,8 @@ public final class InspectableClassModel { * @return The new accessor * @see Type#FIELD */ - static Accessor ofField(String name) { + @NonNull + static Accessor ofField(@NonNull String name) { return new Accessor(name, Type.FIELD); } @@ -111,19 +119,22 @@ public final class InspectableClassModel { * @return The new accessor * @see Type#GETTER */ - static Accessor ofGetter(String name) { + @NonNull + static Accessor ofGetter(@NonNull String name) { return new Accessor(name, Type.GETTER); } - public Accessor(String name, Type type) { + public Accessor(@NonNull String name, @NonNull Type type) { mName = Objects.requireNonNull(name, "Accessor name must not be null"); mType = Objects.requireNonNull(type, "Accessor type must not be null"); } + @NonNull public String getName() { return mName; } + @NonNull public Type getType() { return mType; } @@ -135,6 +146,7 @@ public final class InspectableClassModel { * * @return A string representing the invocation of this accessor */ + @NonNull public String invocation() { switch (mType) { case FIELD: @@ -168,15 +180,15 @@ public final class InspectableClassModel { * Model an inspectable property */ public static final class Property { - private final String mName; - private final Accessor mAccessor; - private final Type mType; + private final @NonNull String mName; + private final @NonNull Accessor mAccessor; + private final @NonNull Type mType; private boolean mAttributeIdInferrableFromR = true; private int mAttributeId = 0; - private List<IntEnumEntry> mIntEnumEntries; - private List<IntFlagEntry> mIntFlagEntries; + private @Nullable List<IntEnumEntry> mIntEnumEntries; + private @Nullable List<IntFlagEntry> mIntFlagEntries; - public Property(String name, Accessor accessor, Type type) { + public Property(@NonNull String name, @NonNull Accessor accessor, @NonNull Type type) { mName = Objects.requireNonNull(name, "Name must not be null"); mAccessor = Objects.requireNonNull(accessor, "Accessor must not be null"); mType = Objects.requireNonNull(type, "Type must not be null"); @@ -204,14 +216,17 @@ public final class InspectableClassModel { mAttributeIdInferrableFromR = attributeIdInferrableFromR; } + @NonNull public String getName() { return mName; } + @NonNull public Accessor getAccessor() { return mAccessor; } + @NonNull public Type getType() { return mType; } @@ -221,6 +236,7 @@ public final class InspectableClassModel { * * @return A list of mapping entries, empty if absent */ + @NonNull public List<IntEnumEntry> getIntEnumEntries() { if (mIntEnumEntries != null) { return mIntEnumEntries; @@ -229,7 +245,7 @@ public final class InspectableClassModel { } } - public void setIntEnumEntries(List<IntEnumEntry> intEnumEntries) { + public void setIntEnumEntries(@NonNull List<IntEnumEntry> intEnumEntries) { mIntEnumEntries = intEnumEntries; } @@ -238,6 +254,7 @@ public final class InspectableClassModel { * * @return A list of mapping entries, empty if absent */ + @NonNull public List<IntFlagEntry> getIntFlagEntries() { if (mIntFlagEntries != null) { return mIntFlagEntries; @@ -246,7 +263,7 @@ public final class InspectableClassModel { } } - public void setIntFlagEntries(List<IntFlagEntry> intFlagEntries) { + public void setIntFlagEntries(@NonNull List<IntFlagEntry> intFlagEntries) { mIntFlagEntries = intFlagEntries; } @@ -321,14 +338,15 @@ public final class InspectableClassModel { * @see android.view.inspector.IntEnumMapping */ public static final class IntEnumEntry { - private final String mName; + private final @NonNull String mName; private final int mValue; - public IntEnumEntry(String name, int value) { + public IntEnumEntry(int value, @NonNull String name) { mName = Objects.requireNonNull(name, "Name must not be null"); mValue = value; } + @NonNull public String getName() { return mName; } @@ -344,29 +362,21 @@ public final class InspectableClassModel { * @see android.view.inspector.IntFlagMapping */ public static final class IntFlagEntry { - private final String mName; + private final @NonNull String mName; private final int mTarget; private final int mMask; - public IntFlagEntry(String name, int target, int mask) { + public IntFlagEntry(int mask, int target, @NonNull String name) { mName = Objects.requireNonNull(name, "Name must not be null"); mTarget = target; mMask = mask; } - public IntFlagEntry(String name, int target) { - this(name, target, target); - } - - /** - * Determine if this entry has a bitmask. - * - * @return True if the bitmask and target are different, false otherwise - */ - public boolean hasMask() { - return mTarget != mMask; + public IntFlagEntry(int target, String name) { + this(target, target, name); } + @NonNull public String getName() { return mName; } diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java index 46819b28c1e8..64a60fbc9179 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java @@ -16,6 +16,8 @@ package android.processor.view.inspector; +import androidx.annotation.NonNull; + import java.util.Optional; import javax.annotation.processing.ProcessingEnvironment; @@ -28,17 +30,17 @@ import javax.lang.model.element.Element; * @see android.view.inspector.InspectableNodeName */ public final class InspectableNodeNameProcessor implements ModelProcessor { - private final String mQualifiedName; - private final ProcessingEnvironment mProcessingEnv; - private final AnnotationUtils mAnnotationUtils; + private final @NonNull String mQualifiedName; + private final @NonNull ProcessingEnvironment mProcessingEnv; + private final @NonNull AnnotationUtils mAnnotationUtils; /** * @param annotationQualifiedName The qualified name of the annotation to process * @param processingEnv The processing environment from the parent processor */ public InspectableNodeNameProcessor( - String annotationQualifiedName, - ProcessingEnvironment processingEnv) { + @NonNull String annotationQualifiedName, + @NonNull ProcessingEnvironment processingEnv) { mQualifiedName = annotationQualifiedName; mProcessingEnv = processingEnv; mAnnotationUtils = new AnnotationUtils(processingEnv); @@ -54,7 +56,7 @@ public final class InspectableNodeNameProcessor implements ModelProcessor { * @param model The model this element should be merged into */ @Override - public void process(Element element, InspectableClassModel model) { + public void process(@NonNull Element element, @NonNull InspectableClassModel model) { try { final AnnotationMirror mirror = mAnnotationUtils.exactlyOneMirror(mQualifiedName, element); diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java index 20de90d51482..2042a68857fb 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java @@ -21,6 +21,8 @@ import android.processor.view.inspector.InspectableClassModel.IntEnumEntry; import android.processor.view.inspector.InspectableClassModel.IntFlagEntry; import android.processor.view.inspector.InspectableClassModel.Property; +import androidx.annotation.NonNull; + import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -45,9 +47,9 @@ import javax.lang.model.type.TypeMirror; * @see android.view.inspector.InspectableProperty */ public final class InspectablePropertyProcessor implements ModelProcessor { - private final String mQualifiedName; - private final ProcessingEnvironment mProcessingEnv; - private final AnnotationUtils mAnnotationUtils; + private final @NonNull String mQualifiedName; + private final @NonNull ProcessingEnvironment mProcessingEnv; + private final @NonNull AnnotationUtils mAnnotationUtils; /** * Regex that matches methods names of the form {@code #getValue()}. @@ -130,15 +132,15 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @param processingEnv The processing environment from the parent processor */ public InspectablePropertyProcessor( - String annotationQualifiedName, - ProcessingEnvironment processingEnv) { + @NonNull String annotationQualifiedName, + @NonNull ProcessingEnvironment processingEnv) { mQualifiedName = annotationQualifiedName; mProcessingEnv = processingEnv; mAnnotationUtils = new AnnotationUtils(processingEnv); } @Override - public void process(Element element, InspectableClassModel model) { + public void process(@NonNull Element element, @NonNull InspectableClassModel model) { try { final AnnotationMirror annotation = mAnnotationUtils.exactlyOneMirror(mQualifiedName, element); @@ -169,7 +171,10 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @return A property for the getter and annotation * @throws ProcessingException If the supplied data is invalid and a property cannot be modeled */ - private Property buildProperty(Element accessor, AnnotationMirror annotation) { + @NonNull + private Property buildProperty( + @NonNull Element accessor, + @NonNull AnnotationMirror annotation) { final Property property; final Optional<String> nameFromAnnotation = mAnnotationUtils .typedValueByName("name", String.class, accessor, annotation); @@ -227,7 +232,7 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @param element The element to check * @throws ProcessingException If the element's modifiers are invalid */ - private void validateModifiers(Element element) { + private void validateModifiers(@NonNull Element element) { final Set<Modifier> modifiers = element.getModifiers(); if (!modifiers.contains(Modifier.PUBLIC)) { @@ -256,7 +261,8 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @return An {@link ExecutableElement} that represents a getter method. * @throws ProcessingException if the element isn't a getter */ - private ExecutableElement ensureGetter(Element element) { + @NonNull + private ExecutableElement ensureGetter(@NonNull Element element) { if (element.getKind() != ElementKind.METHOD) { throw new ProcessingException( String.format("Expected a method, got a %s", element.getKind()), @@ -300,10 +306,10 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @throws ProcessingException If the property type cannot be resolved or is invalid * @see android.view.inspector.InspectableProperty#valueType() */ + @NonNull private Property.Type determinePropertyType( - Element accessor, - AnnotationMirror annotation) { - + @NonNull Element accessor, + @NonNull AnnotationMirror annotation) { final String valueType = mAnnotationUtils .untypedValueByName("valueType", accessor, annotation) .map(Object::toString) @@ -437,7 +443,8 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @return The return or field type of the element * @throws ProcessingException If the element is not a field or a method */ - private TypeMirror extractReturnOrFieldType(Element element) { + @NonNull + private TypeMirror extractReturnOrFieldType(@NonNull Element element) { switch (element.getKind()) { case FIELD: return element.asType(); @@ -460,7 +467,10 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @return The property type returned by the getter * @throws ProcessingException If the return type is not a primitive or an object */ - private Property.Type convertTypeMirrorToPropertyType(TypeMirror typeMirror, Element element) { + @NonNull + private Property.Type convertTypeMirrorToPropertyType( + @NonNull TypeMirror typeMirror, + @NonNull Element element) { switch (unboxType(typeMirror)) { case BOOLEAN: return Property.Type.BOOLEAN; @@ -503,10 +513,10 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @throws ProcessingException If the return type is not an int */ private static void requirePackedIntToBeInt( - String typeName, - Property.Type returnType, - Element accessor, - AnnotationMirror annotation) { + @NonNull String typeName, + @NonNull Property.Type returnType, + @NonNull Element accessor, + @NonNull AnnotationMirror annotation) { if (returnType != Property.Type.INT) { throw new ProcessingException( String.format( @@ -528,7 +538,7 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @param accessor The getter or field to query * @return True if the getter has a color annotation, false otherwise */ - private boolean hasColorAnnotation(Element accessor) { + private boolean hasColorAnnotation(@NonNull Element accessor) { switch (unboxType(extractReturnOrFieldType(accessor))) { case INT: for (String name : COLOR_INT_ANNOTATION_NAMES) { @@ -555,7 +565,7 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @param accessor The getter or field to query * @return True if the accessor is an integer and has a resource ID annotation, false otherwise */ - private boolean hasResourceIdAnnotation(Element accessor) { + private boolean hasResourceIdAnnotation(@NonNull Element accessor) { if (unboxType(extractReturnOrFieldType(accessor)) == TypeKind.INT) { for (String name : RESOURCE_ID_ANNOTATION_NAMES) { if (mAnnotationUtils.hasAnnotation(accessor, name)) { @@ -581,7 +591,8 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @param getter An element representing a getter * @return A string property name */ - private String inferPropertyNameFromGetter(ExecutableElement getter) { + @NonNull + private String inferPropertyNameFromGetter(@NonNull ExecutableElement getter) { final String name = getter.getSimpleName().toString(); if (GETTER_GET_PREFIX.matcher(name).find()) { @@ -600,7 +611,6 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * {@link android.view.inspector.InspectableProperty.EnumMap} annotations into * {@link IntEnumEntry} objects. Further validation should be handled elsewhere * - * @see android.view.inspector.IntEnumMapping * @see android.view.inspector.InspectableProperty#enumMapping() * @param accessor The accessor of the property, used for exceptions * @param annotation The {@link android.view.inspector.InspectableProperty} annotation to @@ -608,9 +618,10 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @return A list of int enum entries, in the order specified in source * @throws ProcessingException if mapping doesn't exist or is invalid */ + @NonNull private List<IntEnumEntry> processEnumMapping( - Element accessor, - AnnotationMirror annotation) { + @NonNull Element accessor, + @NonNull AnnotationMirror annotation) { List<AnnotationMirror> enumAnnotations = mAnnotationUtils.typedArrayValuesByName( "enumMapping", AnnotationMirror.class, accessor, annotation); List<IntEnumEntry> enumEntries = new ArrayList<>(enumAnnotations.size()); @@ -623,23 +634,19 @@ public final class InspectablePropertyProcessor implements ModelProcessor { for (AnnotationMirror enumAnnotation : enumAnnotations) { final String name = mAnnotationUtils.typedValueByName( "name", String.class, accessor, enumAnnotation) - .orElseThrow(() -> { - throw new ProcessingException( - "Name is required for @EnumMap", - accessor, - enumAnnotation); - }); + .orElseThrow(() -> new ProcessingException( + "Name is required for @EnumMap", + accessor, + enumAnnotation)); final int value = mAnnotationUtils.typedValueByName( "value", Integer.class, accessor, enumAnnotation) - .orElseThrow(() -> { - throw new ProcessingException( - "Value is required for @EnumMap", - accessor, - enumAnnotation); - }); + .orElseThrow(() -> new ProcessingException( + "Value is required for @EnumMap", + accessor, + enumAnnotation)); - enumEntries.add(new IntEnumEntry(name, value)); + enumEntries.add(new IntEnumEntry(value, name)); } return enumEntries; @@ -660,9 +667,10 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @return A list of int flags entries, in the order specified in source * @throws ProcessingException if mapping doesn't exist or is invalid */ + @NonNull private List<IntFlagEntry> processFlagMapping( - Element accessor, - AnnotationMirror annotation) { + @NonNull Element accessor, + @NonNull AnnotationMirror annotation) { List<AnnotationMirror> flagAnnotations = mAnnotationUtils.typedArrayValuesByName( "flagMapping", AnnotationMirror.class, accessor, annotation); List<IntFlagEntry> flagEntries = new ArrayList<>(flagAnnotations.size()); @@ -675,29 +683,25 @@ public final class InspectablePropertyProcessor implements ModelProcessor { for (AnnotationMirror flagAnnotation : flagAnnotations) { final String name = mAnnotationUtils.typedValueByName( "name", String.class, accessor, flagAnnotation) - .orElseThrow(() -> { - throw new ProcessingException( - "Name is required for @FlagMap", - accessor, - flagAnnotation); - }); + .orElseThrow(() -> new ProcessingException( + "Name is required for @FlagMap", + accessor, + flagAnnotation)); final int target = mAnnotationUtils.typedValueByName( "target", Integer.class, accessor, flagAnnotation) - .orElseThrow(() -> { - throw new ProcessingException( - "Target is required for @FlagMap", - accessor, - flagAnnotation); - }); + .orElseThrow(() -> new ProcessingException( + "Target is required for @FlagMap", + accessor, + flagAnnotation)); final Optional<Integer> mask = mAnnotationUtils.typedValueByName( "mask", Integer.class, accessor, flagAnnotation); if (mask.isPresent()) { - flagEntries.add(new IntFlagEntry(name, target, mask.get())); + flagEntries.add(new IntFlagEntry(mask.get(), target, name)); } else { - flagEntries.add(new IntFlagEntry(name, target)); + flagEntries.add(new IntFlagEntry(target, name)); } } @@ -710,7 +714,7 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @param type The type mirror to check * @return True if the type is a boolean */ - private boolean isBoolean(TypeMirror type) { + private boolean isBoolean(@NonNull TypeMirror type) { if (type.getKind() == TypeKind.DECLARED) { return mProcessingEnv.getTypeUtils().unboxedType(type).getKind() == TypeKind.BOOLEAN; } else { @@ -724,7 +728,8 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @param typeMirror The type mirror to unbox * @return The same type mirror, or an unboxed primitive version */ - private TypeKind unboxType(TypeMirror typeMirror) { + @NonNull + private TypeKind unboxType(@NonNull TypeMirror typeMirror) { final TypeKind typeKind = typeMirror.getKind(); if (typeKind.isPrimitive()) { @@ -746,7 +751,7 @@ public final class InspectablePropertyProcessor implements ModelProcessor { * @param typeMirror The type mirror to test * @return True if it represents a subclass of color, false otherwise */ - private boolean isColorType(TypeMirror typeMirror) { + private boolean isColorType(@NonNull TypeMirror typeMirror) { final TypeElement colorType = mProcessingEnv .getElementUtils() .getTypeElement("android.graphics.Color"); diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java index 6f6c1aa485ac..c428a4613c95 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java @@ -16,11 +16,12 @@ package android.processor.view.inspector; - import android.processor.view.inspector.InspectableClassModel.IntEnumEntry; import android.processor.view.inspector.InspectableClassModel.IntFlagEntry; import android.processor.view.inspector.InspectableClassModel.Property; +import androidx.annotation.NonNull; + import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; @@ -34,9 +35,11 @@ import com.squareup.javapoet.TypeSpec; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; -import java.util.Optional; +import java.util.stream.Collectors; import javax.annotation.processing.Filer; import javax.lang.model.element.Modifier; @@ -45,8 +48,8 @@ import javax.lang.model.element.Modifier; * Generates a source file defining a {@link android.view.inspector.InspectionCompanion}. */ public final class InspectionCompanionGenerator { - private final Filer mFiler; - private final Class mRequestingClass; + private final @NonNull Filer mFiler; + private final @NonNull Class mRequestingClass; /** * The class name for {@code R.java}. @@ -72,10 +75,9 @@ public final class InspectionCompanionGenerator { "android.view.inspector", "PropertyReader"); /** - * The class name of {@link android.view.inspector.IntEnumMapping}. + * The class name of {@link android.util.SparseArray}. */ - private static final ClassName INT_ENUM_MAPPING = ClassName.get( - "android.view.inspector", "IntEnumMapping"); + private static final ClassName SPARSE_ARRAY = ClassName.get("android.util", "SparseArray"); /** * The class name of {@link android.view.inspector.IntFlagMapping}. @@ -84,17 +86,6 @@ public final class InspectionCompanionGenerator { "android.view.inspector", "IntFlagMapping"); /** - * The {@code mPropertiesMapped} field. - */ - private static final FieldSpec M_PROPERTIES_MAPPED = FieldSpec - .builder(TypeName.BOOLEAN, "mPropertiesMapped", Modifier.PRIVATE) - .initializer("false") - .addJavadoc( - "Set by {@link #mapProperties($T)} once properties have been mapped.\n", - PROPERTY_MAPPER) - .build(); - - /** * The suffix of the generated class name after the class's binary name. */ private static final String GENERATED_CLASS_SUFFIX = "$InspectionCompanion"; @@ -110,7 +101,7 @@ public final class InspectionCompanionGenerator { * @param filer A filer to write the generated source to * @param requestingClass A class object representing the class that invoked the generator */ - public InspectionCompanionGenerator(Filer filer, Class requestingClass) { + public InspectionCompanionGenerator(@NonNull Filer filer, @NonNull Class requestingClass) { mFiler = filer; mRequestingClass = requestingClass; } @@ -121,7 +112,7 @@ public final class InspectionCompanionGenerator { * @param model The model to generated * @throws IOException From the Filer */ - public void generate(InspectableClassModel model) throws IOException { + public void generate(@NonNull InspectableClassModel model) throws IOException { generateFile(model).writeTo(mFiler); } @@ -133,7 +124,8 @@ public final class InspectionCompanionGenerator { * @param model The model to generate from * @return A generated file of an {@link android.view.inspector.InspectionCompanion} */ - JavaFile generateFile(InspectableClassModel model) { + @NonNull + JavaFile generateFile(@NonNull InspectableClassModel model) { return JavaFile .builder(model.getClassName().packageName(), generateTypeSpec(model)) .indent(" ") @@ -147,8 +139,12 @@ public final class InspectionCompanionGenerator { * @param model The model to generate from * @return A TypeSpec of the inspection companion */ - private TypeSpec generateTypeSpec(InspectableClassModel model) { - final List<PropertyIdField> propertyIdFields = generatePropertyIdFields(model); + @NonNull + private TypeSpec generateTypeSpec(@NonNull InspectableClassModel model) { + final List<Property> properties = new ArrayList<>(model.getAllProperties()); + properties.sort(Comparator.comparing(Property::getName)); + + final Map<Property, FieldSpec> fields = generateIdFieldSpecs(properties); TypeSpec.Builder builder = TypeSpec .classBuilder(generateClassName(model)) @@ -158,238 +154,325 @@ public final class InspectionCompanionGenerator { .addJavadoc("Inspection companion for {@link $T}.\n\n", model.getClassName()) .addJavadoc("Generated by {@link $T}\n", getClass()) .addJavadoc("on behalf of {@link $T}.\n", mRequestingClass) - .addField(M_PROPERTIES_MAPPED); - - for (PropertyIdField propertyIdField : propertyIdFields) { - builder.addField(propertyIdField.mFieldSpec); - } + .addField(FieldSpec + .builder(TypeName.BOOLEAN, "mPropertiesMapped", Modifier.PRIVATE) + .initializer("false") + .addJavadoc("Guards against reading properties before mapping them.\n") + .build()) + .addFields(properties.stream().map(fields::get).collect(Collectors.toList())) + .addMethod(generateMapProperties(properties, fields)) + .addMethod(generateReadProperties(properties, fields, model.getClassName())); - builder.addMethod(generateMapProperties(propertyIdFields)) - .addMethod(generateReadProperties(model, propertyIdFields)); - - generateGetNodeName(model).ifPresent(builder::addMethod); + model.getNodeName().ifPresent(name -> builder.addMethod(generateGetNodeName(name))); return builder.build(); } /** - * Build a list of {@link PropertyIdField}'s for a model. - * - * To insure idempotency of the generated code, this method sorts the list of properties - * alphabetically by name. + * Map properties to fields to store the mapping IDs in the generated inspection companion. * - * A {@link NameAllocator} is used to ensure that the field names are valid Java identifiers, - * and it prevents overlaps in names by suffixing them as needed. - * - * @param model The model to get properties from - * @return A list of properties and fields + * @param properties A list of property models + * @return A map of properties to their {@link FieldSpec} */ - private List<PropertyIdField> generatePropertyIdFields(InspectableClassModel model) { - final NameAllocator nameAllocator = new NameAllocator(); - final List<Property> sortedProperties = new ArrayList<>(model.getAllProperties()); - final List<PropertyIdField> propertyIdFields = new ArrayList<>(sortedProperties.size()); - - sortedProperties.sort(Comparator.comparing(Property::getName)); - - for (Property property : sortedProperties) { - // Format a property to a member field name like "someProperty" -> "mSomePropertyId" - final String memberName = String.format( + @NonNull + private Map<Property, FieldSpec> generateIdFieldSpecs(@NonNull List<Property> properties) { + final Map<Property, FieldSpec> fields = new HashMap<>(); + final NameAllocator fieldNames = new NameAllocator(); + fieldNames.newName("mPropertiesMapped"); + + for (Property property : properties) { + final String memberName = fieldNames.newName(String.format( "m%s%sId", property.getName().substring(0, 1).toUpperCase(), - property.getName().substring(1)); - final FieldSpec fieldSpec = FieldSpec - .builder(TypeName.INT, nameAllocator.newName(memberName), Modifier.PRIVATE) - .addJavadoc("Property ID of {@code $L}.\n", property.getName()) - .build(); + property.getName().substring(1))); - propertyIdFields.add(new PropertyIdField(fieldSpec, property)); + fields.put(property, FieldSpec + .builder(TypeName.INT, memberName, Modifier.PRIVATE) + .addJavadoc("Property ID of {@code $L}.\n", property.getName()) + .build()); } - return propertyIdFields; + return fields; } /** - * Generate a method definition for - * {@link android.view.inspector.InspectionCompanion#getNodeName()}, if needed. - * - * If {@link InspectableClassModel#getNodeName()} is empty, This method returns an empty - * optional, otherwise, it generates a simple method that returns the string value of the - * node name. - * - * @param model The model to generate from - * @return The method definition or an empty Optional - */ - private Optional<MethodSpec> generateGetNodeName(InspectableClassModel model) { - return model.getNodeName().map(nodeName -> MethodSpec.methodBuilder("getNodeName") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .returns(String.class) - .addStatement("return $S", nodeName) - .build()); - } - - /** - * Generate a method definition for + * Generates an implementation of * {@link android.view.inspector.InspectionCompanion#mapProperties( * android.view.inspector.PropertyMapper)}. * - * @param propertyIdFields A list of properties to map to ID fields - * @return The method definition + * Example: + * <pre> + * @Override + * public void mapProperties(PropertyMapper propertyMapper) { + * mValueId = propertyMapper.mapInt("value", R.attr.value); + * mPropertiesMapped = true; + * } + * </pre> + * + * @param properties A sorted list of property models + * @param fields A map of properties to their ID field specs + * @return A method definition */ - private MethodSpec generateMapProperties(List<PropertyIdField> propertyIdFields) { + @NonNull + private MethodSpec generateMapProperties( + @NonNull List<Property> properties, + @NonNull Map<Property, FieldSpec> fields) { + final NameAllocator mappingVariables = new NameAllocator(); + final MethodSpec.Builder builder = MethodSpec.methodBuilder("mapProperties") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .addParameter(PROPERTY_MAPPER, "propertyMapper"); - propertyIdFields.forEach(p -> builder.addStatement(generatePropertyMapperInvocation(p))); - builder.addStatement("$N = true", M_PROPERTIES_MAPPED); + // Reserve existing names + mappingVariables.newName("mPropertiesMapped"); + mappingVariables.newName("propertyMapper"); + properties.forEach(p -> mappingVariables.newName(fields.get(p).name)); + + for (Property property : properties) { + final FieldSpec field = fields.get(property); + switch (property.getType()) { + case INT_ENUM: + builder.addCode(generateIntEnumPropertyMapperInvocation( + property, + field, + mappingVariables.newName(property.getName() + "EnumMapping"))); + break; + case INT_FLAG: + builder.addCode(generateIntFlagPropertyMapperInvocation( + property, + field, + mappingVariables.newName(property.getName() + "FlagMapping"))); + break; + default: + builder.addCode(generateSimplePropertyMapperInvocation(property, field)); + } + } + + builder.addStatement("mPropertiesMapped = true"); return builder.build(); } /** - * Generate a method definition for - * {@link android.view.inspector.InspectionCompanion#readProperties( - * Object, android.view.inspector.PropertyReader)}. + * Generate a {@link android.view.inspector.PropertyMapper} invocation. * - * @param model The model to generate from - * @param propertyIdFields A list of properties and ID fields to read from - * @return The method definition + * Example: + * <pre> + * mValueId = propertyMapper.mapInt("value", R.attr.value); + * </pre> + * + * @param property A property model to map + * @param field The property ID field for the property + * @return A code block containing a statement */ - private MethodSpec generateReadProperties( - InspectableClassModel model, - List<PropertyIdField> propertyIdFields) { - final MethodSpec.Builder builder = MethodSpec.methodBuilder("readProperties") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .addParameter(model.getClassName(), "node") - .addParameter(PROPERTY_READER, "propertyReader") - .addCode(generatePropertyMapInitializationCheck()); + @NonNull + private CodeBlock generateSimplePropertyMapperInvocation( + @NonNull Property property, + @NonNull FieldSpec field) { + return CodeBlock + .builder() + .addStatement( + "$N = propertyMapper.map$L($S, $L)", + field, + methodSuffixForPropertyType(property.getType()), + property.getName(), + generateAttributeId(property)) + .build(); + } + + /** + * Generate a {@link android.view.inspector.PropertyMapper} invocation for an int enum. + * + * Example: + * <pre> + * final SparseArray<String> valueEnumMapping = new SparseArray<>(); + * valueEnumMapping.put(1, "ONE"); + * valueEnumMapping.put(2, "TWO"); + * mValueId = propertyMapper.mapIntEnum("value", R.attr.value, valueEnumMapping::get); + * </pre> + * + * @param property A property model to map + * @param field The property ID field for the property + * @param variable The name of a local variable to use to store the mapping in + * @return A code block containing a series of statements + */ + @NonNull + private CodeBlock generateIntEnumPropertyMapperInvocation( + @NonNull Property property, + @NonNull FieldSpec field, + @NonNull String variable) { + final CodeBlock.Builder builder = CodeBlock.builder(); + + final List<IntEnumEntry> enumEntries = property.getIntEnumEntries(); + enumEntries.sort(Comparator.comparing(IntEnumEntry::getValue)); + + builder.addStatement( + "final $1T<$2T> $3N = new $1T<>()", + SPARSE_ARRAY, + String.class, + variable); - for (PropertyIdField propertyIdField : propertyIdFields) { + for (IntEnumEntry enumEntry : enumEntries) { builder.addStatement( - "propertyReader.read$L($N, node.$L)", - methodSuffixForPropertyType(propertyIdField.mProperty.getType()), - propertyIdField.mFieldSpec, - propertyIdField.mProperty.getAccessor().invocation()); + "$N.put($L, $S)", + variable, + enumEntry.getValue(), + enumEntry.getName()); } + builder.addStatement( + "$N = propertyMapper.mapIntEnum($S, $L, $N::get)", + field, + property.getName(), + generateAttributeId(property), + variable); + return builder.build(); } /** - * Generate a statement maps a property with a {@link android.view.inspector.PropertyMapper}. + * Generate a {@link android.view.inspector.PropertyMapper} invocation for an int flag. * - * @param propertyIdField The property model and ID field to generate from - * @return A statement that invokes property mapper method + * Example: + * <pre> + * final IntFlagMapping valueFlagMapping = new IntFlagMapping(); + * valueFlagMapping.add(0x00000003, 0x00000001, "ONE"); + * valueFlagMapping.add(0x00000003, 0x00000002, "TWO"); + * mValueId = propertyMapper.mapIntFlag("value", R.attr.value, valueFlagMapping::get); + * </pre> + * + * @param property A property model to map + * @param field The property ID field for the property + * @param variable The name of a local variable to use to store the mapping in + * @return A code block containing a series of statements */ - private CodeBlock generatePropertyMapperInvocation(PropertyIdField propertyIdField) { + @NonNull + private CodeBlock generateIntFlagPropertyMapperInvocation( + @NonNull Property property, + @NonNull FieldSpec field, + @NonNull String variable) { final CodeBlock.Builder builder = CodeBlock.builder(); - final Property property = propertyIdField.mProperty; - final FieldSpec fieldSpec = propertyIdField.mFieldSpec; - builder.add( - "$N = propertyMapper.map$L($S,$W", - fieldSpec, - methodSuffixForPropertyType(property.getType()), - property.getName()); + final List<IntFlagEntry> flagEntries = property.getIntFlagEntries(); + flagEntries.sort(Comparator.comparing(IntFlagEntry::getName)); + + builder.addStatement( + "final $1T $2N = new $1T()", + INT_FLAG_MAPPING, + variable); + + for (IntFlagEntry flagEntry : flagEntries) { + builder.addStatement( + "$N.add($L, $L, $S)", + variable, + hexLiteral(flagEntry.getMask()), + hexLiteral(flagEntry.getTarget()), + flagEntry.getName()); + } + builder.addStatement( + "$N = propertyMapper.mapIntFlag($S, $L, $N::get)", + field, + property.getName(), + generateAttributeId(property), + variable); + + return builder.build(); + } + + /** + * Generate a literal attribute ID or reference to {@link android.R.attr}. + * + * Example: {@code R.attr.value} or {@code 0xdecafbad}. + * + * @param property A property model + * @return A code block containing the attribute ID + */ + @NonNull + private CodeBlock generateAttributeId(@NonNull Property property) { if (property.isAttributeIdInferrableFromR()) { - builder.add("$T.attr.$L", R_CLASS_NAME, property.getName()); + return CodeBlock.of("$T.attr.$L", R_CLASS_NAME, property.getName()); } else { if (property.getAttributeId() == ID_NULL) { - builder.add("$L", ID_NULL); + return CodeBlock.of("$L", ID_NULL); } else { - builder.add("$L", hexLiteral(property.getAttributeId())); + return CodeBlock.of("$L", hexLiteral(property.getAttributeId())); } } - - switch (property.getType()) { - case INT_ENUM: - builder.add(",$W"); - builder.add(generateIntEnumMappingBuilder(property.getIntEnumEntries())); - break; - case INT_FLAG: - builder.add(",$W"); - builder.add(generateIntFlagMappingBuilder(property.getIntFlagEntries())); - break; - } - - return builder.add(")").build(); } /** - * Generate a check that throws - * {@link android.view.inspector.InspectionCompanion.UninitializedPropertyMapException} - * if the properties haven't been initialized. + * Generate an implementation of + * {@link android.view.inspector.InspectionCompanion#readProperties(Object, + * android.view.inspector.PropertyReader)}. * + * Example: * <pre> - * if (!mPropertiesMapped) { - * throw new InspectionCompanion.UninitializedPropertyMapException(); + * @Override + * public void readProperties(MyNode node, PropertyReader propertyReader) { + * if (!mPropertiesMapped) { + * throw new InspectionCompanion.UninitializedPropertyMapException(); + * } + * propertyReader.readInt(mValueId, node.getValue()); * } * </pre> * - * @return A codeblock containing the property map initialization check + * @param properties An ordered list of property models + * @param fields A map from properties to their field specs + * @param nodeClass The class of the node, used for the parameter type + * @return A method definition */ - private CodeBlock generatePropertyMapInitializationCheck() { - return CodeBlock.builder() - .beginControlFlow("if (!$N)", M_PROPERTIES_MAPPED) + @NonNull + private MethodSpec generateReadProperties( + @NonNull List<Property> properties, + @NonNull Map<Property, FieldSpec> fields, + @NonNull ClassName nodeClass) { + final MethodSpec.Builder builder = MethodSpec.methodBuilder("readProperties") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .addParameter(nodeClass, "node") + .addParameter(PROPERTY_READER, "propertyReader") + .beginControlFlow("if (!mPropertiesMapped)") .addStatement( "throw new $T()", INSPECTION_COMPANION.nestedClass("UninitializedPropertyMapException")) - .endControlFlow() - .build(); + .endControlFlow(); + + for (Property property : properties) { + builder.addStatement( + "propertyReader.read$L($N, node.$L)", + methodSuffixForPropertyType(property.getType()), + fields.get(property), + property.getAccessor().invocation()); + } + + return builder.build(); } /** - * Generate an invocation of {@link android.view.inspector.IntEnumMapping.Builder}. + * Generate an implementation of + * {@link android.view.inspector.InspectionCompanion#getNodeName()}. * + * Example: * <pre> - * new IntEnumMapping.Builder() - * .addValue("ONE", 1) - * .build() + * @Override + * public String getNodeName() { + * return "nodeName"; + * } * </pre> * - * @return A codeblock containing the an int enum mapping builder + * @param nodeName The name of this node + * @return A method definition that returns the node name */ - private CodeBlock generateIntEnumMappingBuilder(List<IntEnumEntry> intEnumEntries) { - final ArrayList<IntEnumEntry> sortedEntries = new ArrayList<>(intEnumEntries); - sortedEntries.sort(Comparator.comparing(IntEnumEntry::getValue)); - - final CodeBlock.Builder builder = CodeBlock.builder() - .add("new $T()$>", INT_ENUM_MAPPING.nestedClass("Builder")); - - for (IntEnumEntry entry : sortedEntries) { - builder.add("\n.addValue($S, $L)", entry.getName(), entry.getValue()); - } - - return builder.add("\n.build()$<").build(); - } - - private CodeBlock generateIntFlagMappingBuilder(List<IntFlagEntry> intFlagEntries) { - final ArrayList<IntFlagEntry> sortedEntries = new ArrayList<>(intFlagEntries); - sortedEntries.sort(Comparator.comparing(IntFlagEntry::getName)); - - final CodeBlock.Builder builder = CodeBlock.builder() - .add("new $T()$>", INT_FLAG_MAPPING.nestedClass("Builder")); - - for (IntFlagEntry entry : sortedEntries) { - if (entry.hasMask()) { - builder.add( - "\n.addFlag($S, $L, $L)", - entry.getName(), - hexLiteral(entry.getTarget()), - hexLiteral(entry.getMask())); - } else { - builder.add( - "\n.addFlag($S, $L)", - entry.getName(), - hexLiteral(entry.getTarget())); - } - } - - return builder.add("\n.build()$<").build(); + @NonNull + private MethodSpec generateGetNodeName(@NonNull String nodeName) { + return MethodSpec.methodBuilder("getNodeName") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .returns(String.class) + .addStatement("return $S", nodeName) + .build(); } /** @@ -397,14 +480,15 @@ public final class InspectionCompanionGenerator { * * The generated class is added to the same package as the source class. If the class in the * model is a nested class, the nested class names are joined with {@code "$"}. The suffix - * {@code "$$InspectionCompanion"} is always added the the generated name. E.g.: For modeled + * {@code "$InspectionCompanion"} is always added to the generated name. E.g.: For modeled * class {@code com.example.Outer.Inner}, the generated class name will be - * {@code com.example.Outer$Inner$$InspectionCompanion}. + * {@code com.example.Outer$Inner$InspectionCompanion}. * * @param model The model to generate from * @return A class name for the generated inspection companion class */ - private static ClassName generateClassName(InspectableClassModel model) { + @NonNull + private static ClassName generateClassName(@NonNull InspectableClassModel model) { final ClassName className = model.getClassName(); return ClassName.get( @@ -418,7 +502,8 @@ public final class InspectionCompanionGenerator { * @param type The requested property type * @return A method suffix */ - private static String methodSuffixForPropertyType(Property.Type type) { + @NonNull + private static String methodSuffixForPropertyType(@NonNull Property.Type type) { switch (type) { case BOOLEAN: return "Boolean"; @@ -453,20 +538,14 @@ public final class InspectionCompanionGenerator { } } - private static String hexLiteral(int value) { - return String.format("0x%08x", value); - } - /** - * Value class that holds a {@link Property} and a {@link FieldSpec} for that property. + * Format an int as an 8 digit hex literal + * + * @param value The value to format + * @return A string representation of the hex literal */ - private static final class PropertyIdField { - private final FieldSpec mFieldSpec; - private final Property mProperty; - - private PropertyIdField(FieldSpec fieldSpec, Property property) { - mFieldSpec = fieldSpec; - mProperty = property; - } + @NonNull + private static String hexLiteral(int value) { + return String.format("0x%08x", value); } } diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java index 6f522608a9b4..ab38f4c9e1b0 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java @@ -16,6 +16,8 @@ package android.processor.view.inspector; +import androidx.annotation.NonNull; + import javax.lang.model.element.Element; /** @@ -28,5 +30,5 @@ public interface ModelProcessor { * @param element The annotated element to operate on * @param model The model this element should be merged into */ - void process(Element element, InspectableClassModel model); + void process(@NonNull Element element, @NonNull InspectableClassModel model); } diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java index fd142c62e8e3..d9ed1fb9f343 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java @@ -18,6 +18,8 @@ package android.processor.view.inspector; import static javax.tools.Diagnostic.Kind.ERROR; +import androidx.annotation.NonNull; + import com.squareup.javapoet.ClassName; import java.io.IOException; @@ -63,7 +65,9 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { } @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + public boolean process( + @NonNull Set<? extends TypeElement> annotations, + @NonNull RoundEnvironment roundEnv) { final Map<String, InspectableClassModel> modelMap = new HashMap<>(); for (TypeElement annotation : annotations) { @@ -109,9 +113,9 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { * @param modelMap A map of qualified class names to models */ private void runModelProcessor( - Set<? extends Element> elements, - ModelProcessor processor, - Map<String, InspectableClassModel> modelMap) { + @NonNull Set<? extends Element> elements, + @NonNull ModelProcessor processor, + @NonNull Map<String, InspectableClassModel> modelMap) { for (Element element : elements) { final Optional<TypeElement> classElement = enclosingClassElement(element); @@ -149,7 +153,7 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { * @param typeElement A type element representing the class to check * @return f the class contains a class named {@code InspectionCompanion} */ - private static boolean hasNestedInspectionCompanion(TypeElement typeElement) { + private static boolean hasNestedInspectionCompanion(@NonNull TypeElement typeElement) { for (TypeElement nestedClass : ElementFilter.typesIn(typeElement.getEnclosedElements())) { if (nestedClass.getSimpleName().toString().equals("InspectionCompanion")) { return true; @@ -167,7 +171,8 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { * @param element An element to search from * @return A TypeElement of the nearest enclosing class or an empty optional */ - private static Optional<TypeElement> enclosingClassElement(Element element) { + @NonNull + private static Optional<TypeElement> enclosingClassElement(@NonNull Element element) { Element cursor = element; while (cursor != null) { @@ -186,7 +191,7 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { * * @param message Message to print */ - private void fail(String message) { + private void fail(@NonNull String message) { processingEnv.getMessager().printMessage(ERROR, message); } @@ -196,7 +201,7 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { * @param message Message to print * @param element The element that failed */ - private void fail(String message, Element element) { + private void fail(@NonNull String message, @NonNull Element element) { processingEnv.getMessager().printMessage(ERROR, message, element); } } diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java index b4c6466b2b2f..7389c240049b 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java @@ -18,6 +18,9 @@ package android.processor.view.inspector; import static javax.tools.Diagnostic.Kind.ERROR; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import javax.annotation.processing.Messager; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; @@ -27,27 +30,30 @@ import javax.lang.model.element.Element; * Internal exception used to signal an error processing an annotation. */ final class ProcessingException extends RuntimeException { - private final Element mElement; - private final AnnotationMirror mAnnotationMirror; - private final AnnotationValue mAnnotationValue; + private final @Nullable Element mElement; + private final @Nullable AnnotationMirror mAnnotationMirror; + private final @Nullable AnnotationValue mAnnotationValue; - ProcessingException(String message) { + ProcessingException(@NonNull String message) { this(message, null, null, null); } - ProcessingException(String message, Element element) { + ProcessingException(@NonNull String message, @NonNull Element element) { this(message, element, null, null); } - ProcessingException(String message, Element element, AnnotationMirror annotationMirror) { + ProcessingException( + @NonNull String message, + @NonNull Element element, + @NonNull AnnotationMirror annotationMirror) { this(message, element, annotationMirror, null); } ProcessingException( - String message, - Element element, - AnnotationMirror annotationMirror, - AnnotationValue annotationValue) { + @NonNull String message, + @Nullable Element element, + @Nullable AnnotationMirror annotationMirror, + @Nullable AnnotationValue annotationValue) { super(message); mElement = element; mAnnotationMirror = annotationMirror; @@ -59,7 +65,7 @@ final class ProcessingException extends RuntimeException { * * @param messager A Messager to print to */ - void print(Messager messager) { + void print(@NonNull Messager messager) { if (mElement != null) { if (mAnnotationMirror != null) { if (mAnnotationValue != null) { diff --git a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java index 4eed5040eb51..3ec620a1a4bf 100644 --- a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java +++ b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java @@ -118,9 +118,9 @@ public class InspectionCompanionGeneratorTest { Property.Type.INT_ENUM); property.setIntEnumEntries(Arrays.asList( - new IntEnumEntry("THREE", 3), - new IntEnumEntry("TWO", 2), - new IntEnumEntry("ONE", 1))); + new IntEnumEntry(3, "THREE"), + new IntEnumEntry(2, "TWO"), + new IntEnumEntry(1, "ONE"))); mModel.putProperty(property); @@ -136,9 +136,9 @@ public class InspectionCompanionGeneratorTest { property.setAttributeIdInferrableFromR(false); property.setIntFlagEntries(Arrays.asList( - new IntFlagEntry("TURBO", 0x1, 0x3), - new IntFlagEntry("OVERDRIVE", 0x2, 0x3), - new IntFlagEntry("WARP", 0x4) + new IntFlagEntry(0x3, 0x1, "TURBO"), + new IntFlagEntry(0x3, 0x2, "OVERDRIVE"), + new IntFlagEntry(0x4, "WARP") )); assertGeneratedFileEquals("IntFlag"); diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt index 9a0fe5b76e27..e4a8ba49e63b 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt @@ -14,7 +14,7 @@ import java.lang.Override; */ public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> { /** - * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped. + * Guards against reading properties before mapping them. */ private boolean mPropertiesMapped = false; diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt index b491de1d63ad..fa9dbfd9a590 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntEnum.java.txt @@ -1,11 +1,12 @@ package com.android.node; import android.R; +import android.util.SparseArray; import android.view.inspector.InspectionCompanion; -import android.view.inspector.IntEnumMapping; import android.view.inspector.PropertyMapper; import android.view.inspector.PropertyReader; import java.lang.Override; +import java.lang.String; /** * Inspection companion for {@link TestNode}. @@ -15,7 +16,7 @@ import java.lang.Override; */ public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> { /** - * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped. + * Guards against reading properties before mapping them. */ private boolean mPropertiesMapped = false; @@ -26,12 +27,11 @@ public final class TestNode$InspectionCompanion implements InspectionCompanion<T @Override public void mapProperties(PropertyMapper propertyMapper) { - mIntEnumPropertyId = propertyMapper.mapIntEnum("intEnumProperty", R.attr.intEnumProperty, - new IntEnumMapping.Builder() - .addValue("ONE", 1) - .addValue("TWO", 2) - .addValue("THREE", 3) - .build()); + final SparseArray<String> intEnumPropertyEnumMapping = new SparseArray<>(); + intEnumPropertyEnumMapping.put(1, "ONE"); + intEnumPropertyEnumMapping.put(2, "TWO"); + intEnumPropertyEnumMapping.put(3, "THREE"); + mIntEnumPropertyId = propertyMapper.mapIntEnum("intEnumProperty", R.attr.intEnumProperty, intEnumPropertyEnumMapping::get); mPropertiesMapped = true; } diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt index 7d180580b45e..ed3d8ee40ffb 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/IntFlag.java.txt @@ -14,7 +14,7 @@ import java.lang.Override; */ public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> { /** - * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped. + * Guards against reading properties before mapping them. */ private boolean mPropertiesMapped = false; @@ -25,11 +25,11 @@ public final class TestNode$InspectionCompanion implements InspectionCompanion<T @Override public void mapProperties(PropertyMapper propertyMapper) { - mIntFlagId = propertyMapper.mapIntFlag("intFlag", 0, new IntFlagMapping.Builder() - .addFlag("OVERDRIVE", 0x00000002, 0x00000003) - .addFlag("TURBO", 0x00000001, 0x00000003) - .addFlag("WARP", 0x00000004) - .build()); + final IntFlagMapping intFlagFlagMapping = new IntFlagMapping(); + intFlagFlagMapping.add(0x00000003, 0x00000002, "OVERDRIVE"); + intFlagFlagMapping.add(0x00000003, 0x00000001, "TURBO"); + intFlagFlagMapping.add(0x00000004, 0x00000004, "WARP"); + mIntFlagId = propertyMapper.mapIntFlag("intFlag", 0, intFlagFlagMapping::get); mPropertiesMapped = true; } diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt index dc27abbe6fbd..4514ed9ac3dc 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NestedClass.java.txt @@ -13,7 +13,7 @@ import java.lang.Override; */ public final class Outer$Inner$InspectionCompanion implements InspectionCompanion<Outer.Inner> { /** - * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped. + * Guards against reading properties before mapping them. */ private boolean mPropertiesMapped = false; diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt index 738bcd3dab36..563f93dfe560 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt @@ -13,7 +13,7 @@ import java.lang.Override; */ public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> { /** - * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped. + * Guards against reading properties before mapping them. */ private boolean mPropertiesMapped = false; diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt index 82dd66e2597e..ffa1f0be02d4 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NodeName.java.txt @@ -14,7 +14,7 @@ import java.lang.String; */ public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> { /** - * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped. + * Guards against reading properties before mapping them. */ private boolean mPropertiesMapped = false; diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt index 08ea69679086..cb85767ee2d3 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt @@ -14,7 +14,7 @@ import java.lang.Override; */ public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> { /** - * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped. + * Guards against reading properties before mapping them. */ private boolean mPropertiesMapped = false; diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt index 3bfa78ac857f..731d41073810 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SuppliedAttributeId.java.txt @@ -13,7 +13,7 @@ import java.lang.Override; */ public final class TestNode$InspectionCompanion implements InspectionCompanion<TestNode> { /** - * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped. + * Guards against reading properties before mapping them. */ private boolean mPropertiesMapped = false; @@ -24,8 +24,7 @@ public final class TestNode$InspectionCompanion implements InspectionCompanion<T @Override public void mapProperties(PropertyMapper propertyMapper) { - mSuppliedAttributePropertyId = propertyMapper.mapInt("suppliedAttributeProperty", - 0xdecafbad); + mSuppliedAttributePropertyId = propertyMapper.mapInt("suppliedAttributeProperty", 0xdecafbad); mPropertiesMapped = true; } |