diff options
author | Yigit Boyar <yboyar@google.com> | 2018-10-19 14:15:57 -0700 |
---|---|---|
committer | Yigit Boyar <yboyar@google.com> | 2018-10-19 14:47:39 -0700 |
commit | dc62f2f3563222b320f1406ab4ae4dfa67fbaa3e (patch) | |
tree | 6f9cb6e45c2a0a24bfc0b364a457f10dbcfc4061 /compiler | |
parent | 2ec6c75f754b0f6ffdf1ab87920c76cb5679aeba (diff) | |
download | data-binding-dc62f2f3563222b320f1406ab4ae4dfa67fbaa3e.tar.gz |
Change ModelClass to use Lists instead of Arrays
This avoids creating an unnecessary array.
Also moved Injected class to be kotlin as well.
Bug: 117808327
Test: existing tests
Change-Id: I481106b1089e5d1066ec0733683876926d519fad
Diffstat (limited to 'compiler')
8 files changed, 186 insertions, 298 deletions
diff --git a/compiler/src/main/java/android/databinding/tool/CompilerChef.java b/compiler/src/main/java/android/databinding/tool/CompilerChef.java index 46cd6724..d93d701d 100644 --- a/compiler/src/main/java/android/databinding/tool/CompilerChef.java +++ b/compiler/src/main/java/android/databinding/tool/CompilerChef.java @@ -163,6 +163,9 @@ public class CompilerChef { String fieldName = bindingTargetBundle.getId(); if (fields.add(fieldName)) { String fieldType = bindingTargetBundle.getInterfaceType(); + if (fieldType == null) { + fieldType = bindingTargetBundle.getFullClassName(); + } bindingClass.addField(fieldName, fieldType); } } diff --git a/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java b/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java deleted file mode 100644 index c100bfd3..00000000 --- a/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2016 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.databinding.tool.reflection; - -import android.databinding.tool.ext.ExtKt; -import android.databinding.tool.util.StringUtils; - -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.TypeName; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * A class that can be used by ModelAnalyzer without any backing model. This is used - * for ViewDataBinding subclasses that haven't been generated yet, but we still want - * to resolve methods and fields for them. - * - * @see ModelAnalyzer#injectClass(InjectedClass) - */ -public class InjectedClass extends ModelClass { - private final String mClassName; - private final String mSuperClass; - private final List<InjectedMethod> mMethods = new ArrayList<InjectedMethod>(); - private final List<InjectedField> mFields = new ArrayList<InjectedField>(); - - public InjectedClass(String className, String superClass) { - mClassName = className; - mSuperClass = superClass; - } - - public void addVariable(String name, String type, ImportBag imports) { - String capName = StringUtils.capitalize(name); - String setName = "set" + capName; - String getName = "get" + capName; - addMethod(new InjectedMethod(this, false, getName, imports, type)); - addMethod(new InjectedMethod(this, false, setName, imports, - "void", type)); - } - - public void addField(String name, String type) { - addField(new InjectedField(name, type)); - } - - public void addField(InjectedField field) { - mFields.add(field); - } - - public void addMethod(InjectedMethod method) { - mMethods.add(method); - } - - @Override - public String toJavaCode() { - return mClassName; - } - - @Override - public boolean isArray() { - return false; - } - - @Override - public ModelClass getComponentType() { - return null; - } - - @Override - public boolean isNullable() { - return true; - } - - @Override - public boolean isPrimitive() { - return false; - } - - @Override - public boolean isBoolean() { - return false; - } - - @Override - public boolean isChar() { - return false; - } - - @Override - public boolean isByte() { - return false; - } - - @Override - public boolean isShort() { - return false; - } - - @Override - public boolean isInt() { - return false; - } - - @Override - public boolean isLong() { - return false; - } - - @Override - public boolean isFloat() { - return false; - } - - @Override - public boolean isDouble() { - return false; - } - - @Override - public boolean isGeneric() { - return false; - } - - @Override - public List<ModelClass> getTypeArguments() { - return null; - } - - @Override - public boolean isTypeVar() { - return false; - } - - @Override - public boolean isWildcard() { - return false; - } - - @Override - public boolean isInterface() { - return false; - } - - @Override - public boolean isVoid() { - return false; - } - - @Override - public ModelClass unbox() { - return this; - } - - @Override - public ModelClass box() { - return this; - } - - @Override - public boolean isObservable() { - return getSuperclass().isObservable(); - } - - @Override - public boolean isAssignableFrom(ModelClass that) { - ModelClass superClass = that; - while (superClass != null && !superClass.isObject()) { - if (superClass.toJavaCode().equals(mClassName)) { - return true; - } - } - return false; - } - - @Override - public ModelClass getSuperclass() { - return ModelAnalyzer.getInstance().findClass(mSuperClass, null); - } - - @Override - public ModelClass erasure() { - return this; - } - - @Override - public String getJniDescription() { - return TypeUtil.getInstance().getDescription(this); - } - - @Override - public ModelField[] getDeclaredFields() { - ModelClass superClass = getSuperclass(); - final ModelField[] superFields = superClass.getDeclaredFields(); - final int initialCount = superFields.length; - final int fieldCount = initialCount + mFields.size(); - final ModelField[] fields = Arrays.copyOf(superFields, fieldCount); - for (int i = 0; i < mFields.size(); i++) { - fields[i + initialCount] = mFields.get(i); - } - return fields; - } - - @Override - public ModelMethod[] getDeclaredMethods() { - ModelClass superClass = getSuperclass(); - final ModelMethod[] superMethods = superClass.getDeclaredMethods(); - final int initialCount = superMethods.length; - final int methodCount = initialCount + mMethods.size(); - final ModelMethod[] methods = Arrays.copyOf(superMethods, methodCount); - for (int i = 0; i < mMethods.size(); i++) { - methods[i + initialCount] = mMethods.get(i); - } - return methods; - } - - @Override - public TypeName getTypeName() { - ModelAnalyzer instance = ModelAnalyzer.getInstance(); - if (instance == null) { - return ExtKt.toTypeName(mClassName, false); - } - return ExtKt.toTypeName(mClassName, instance.libTypes); - } - - @Override - public String toString() { - return "Injected Class: " + mClassName; - } -} diff --git a/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.kt b/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.kt new file mode 100644 index 00000000..d3103c3e --- /dev/null +++ b/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.kt @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2016 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.databinding.tool.reflection + +import android.databinding.tool.ext.toTypeName +import android.databinding.tool.util.StringUtils +import com.squareup.javapoet.TypeName +import java.util.* + +/** + * A class that can be used by ModelAnalyzer without any backing model. This is used + * for ViewDataBinding subclasses that haven't been generated yet, but we still want + * to resolve methods and fields for them. + * + * @see ModelAnalyzer.injectClass + */ +class InjectedClass(private val mClassName: String, private val mSuperClass: String) : ModelClass() { + private val mMethods = ArrayList<InjectedMethod>() + private val mFields = ArrayList<InjectedField>() + + override val isArray = false + + override val componentType: ModelClass? = null + + override val isNullable = true + + override val isPrimitive = false + + override val isBoolean = false + + override val isChar = false + + override val isByte = false + + override val isShort = false + + override val isInt = false + + override val isLong = false + + override val isFloat = false + + override val isDouble = false + + override val isGeneric = false + + override val typeArguments: List<ModelClass>? = null + + override val isTypeVar = false + + override val isWildcard = false + + override val isInterface = false + + override val isVoid = false + + override val isObservable by lazy(LazyThreadSafetyMode.NONE) { + superclass.isObservable + } + + override val superclass by lazy(LazyThreadSafetyMode.NONE) { + ModelAnalyzer.getInstance().findClass(mSuperClass, null)!! + } + + override val jniDescription: String by lazy(LazyThreadSafetyMode.NONE) { + TypeUtil.getInstance().getDescription(this) + } + + // not cached because it is mutable + override val declaredFields: List<ModelField> + get() { + return superclass.declaredFields + mFields + } + + // not cached because it is mutable + override val declaredMethods: List<ModelMethod> + get() { + return superclass.declaredMethods + mMethods + } + + override val typeName: TypeName by lazy(LazyThreadSafetyMode.NONE) { + val instance = ModelAnalyzer.getInstance() + mClassName.toTypeName(instance.libTypes) + } + + fun addVariable(name: String, type: String, imports: ImportBag) { + val capName = StringUtils.capitalize(name) + val setName = "set" + capName!! + val getName = "get$capName" + addMethod(InjectedMethod(this, false, getName, imports, type)) + addMethod(InjectedMethod(this, false, setName, imports, + "void", type)) + } + + fun addField(name: String, type: String) { + addField(InjectedField(name, type)) + } + + private fun addField(field: InjectedField) { + mFields.add(field) + } + + fun addMethod(method: InjectedMethod) { + mMethods.add(method) + } + + override fun toJavaCode() = mClassName + + override fun unbox() = this + + override fun box() = this + + override fun isAssignableFrom(that: ModelClass?): Boolean { + var maybeSuper = that + while (maybeSuper != null && !maybeSuper.isObject) { + if (maybeSuper.toJavaCode() == mClassName) { + return true + } + maybeSuper = maybeSuper.superclass + } + return false + } + + override fun erasure() = this + + override fun toString() = "Injected Class: $mClassName" +} diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.kt b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.kt index a44fcf4c..f72bd6f1 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.kt +++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.kt @@ -297,9 +297,9 @@ abstract class ModelClass { return false } - abstract val declaredFields: Array<ModelField> + abstract val declaredFields: List<ModelField> - abstract val declaredMethods: Array<ModelMethod> + abstract val declaredMethods: List<ModelMethod> // implementation only so that PSI model doesn't break open val typeName: TypeName @@ -365,13 +365,13 @@ abstract class ModelClass { * `args` parameters. */ private fun getMethods(name: String, args: List<ModelClass>, staticOnly: Boolean, - allowProtected: Boolean, unwrapObservableFields: Boolean): Array<ModelMethod> { + allowProtected: Boolean, unwrapObservableFields: Boolean): List<ModelMethod> { return declaredMethods.filter { method -> (method.isPublic || (allowProtected && method.isProtected)) && (!staticOnly || method.isStatic) && name == method.name && method.acceptsArguments(args, unwrapObservableFields) - }.toTypedArray() + } } /** @@ -381,13 +381,13 @@ abstract class ModelClass { * @param numParameters The number of parameters that the method should take * @return An array containing all public methods with the given name and number of parameters. */ - fun getMethods(name: String, numParameters: Int): Array<ModelMethod> { + fun getMethods(name: String, numParameters: Int): List<ModelMethod> { return declaredMethods.filter { method -> method.isPublic && !method.isStatic && name == method.name && method.parameterTypes.size == numParameters - }.toTypedArray() + } } /** @@ -574,15 +574,11 @@ abstract class ModelClass { * listener methods during Expr.resolveListeners. */ fun findMethods(name: String, staticOnly: Boolean): List<ModelMethod> { - val methods = declaredMethods - val matching = ArrayList<ModelMethod>() - for (method in methods) { - if (method.name == name && (!staticOnly || method.isStatic) && - method.isPublic) { - matching.add(method) - } + return declaredMethods.filter { method -> + method.isPublic && + method.name == name && + (!staticOnly || method.isStatic) } - return matching } override fun equals(other: Any?): Boolean { diff --git a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationClass.kt b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationClass.kt index eeec3fe0..75805a63 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationClass.kt +++ b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationClass.kt @@ -245,12 +245,11 @@ class AnnotationClass( val elementUtils = elementUtils val typeElement = declaredType.asElement() as TypeElement val members = elementUtils.getAllMembers(typeElement) - val methods = ElementFilter.methodsIn(members) - Array(methods.size) { - AnnotationMethod(declaredType, methods[it]) as ModelMethod + ElementFilter.methodsIn(members).map { + AnnotationMethod(declaredType, it) as ModelMethod } } else { - emptyArray() + emptyList() } } @@ -297,12 +296,11 @@ class AnnotationClass( val elementUtils = elementUtils val typeElement = declaredType.asElement() as TypeElement val members = elementUtils.getAllMembers(typeElement) - val fields = ElementFilter.fieldsIn(members) - Array(fields.size) { - AnnotationField(declaredType, fields[it]) as ModelField + ElementFilter.fieldsIn(members).map { + AnnotationField(declaredType, it) as ModelField } } else { - emptyArray() + emptyList() } } diff --git a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java index 4fce56ef..c04d73db 100644 --- a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java +++ b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java @@ -731,7 +731,7 @@ public class SetterStore { List<ModelClass> args = new ArrayList<>(); args.add(argumentType); for (String name : setterCandidates) { - ModelMethod[] methods = viewType.getMethods(name, 1); + List<ModelMethod> methods = viewType.getMethods(name, 1); for (ModelMethod method : methods) { ModelClass[] parameterTypes = method.getParameterTypes(); diff --git a/compiler/src/test/java/android/databinding/tool/reflection/SdkVersionTest.java b/compiler/src/test/java/android/databinding/tool/reflection/SdkVersionTest.java index 58153656..8c9114d5 100644 --- a/compiler/src/test/java/android/databinding/tool/reflection/SdkVersionTest.java +++ b/compiler/src/test/java/android/databinding/tool/reflection/SdkVersionTest.java @@ -30,14 +30,14 @@ public class SdkVersionTest { public void testApiVersionsFromResources() { SdkUtil.get().swapApiChecker(new SdkUtil.ApiChecker(null)); ModelClass view = ModelAnalyzer.getInstance().findClass("android.widget.TextView", null); - ModelMethod isSuggestionsEnabled = view.getMethods("isSuggestionsEnabled", 0)[0]; + ModelMethod isSuggestionsEnabled = view.getMethods("isSuggestionsEnabled", 0).get(0); assertEquals(14, SdkUtil.get().getMinApi(isSuggestionsEnabled)); } @Test public void testNewApiMethod() { ModelClass view = ModelAnalyzer.getInstance().findClass("android.view.View", null); - ModelMethod setElevation = view.getMethods("setElevation", 1)[0]; + ModelMethod setElevation = view.getMethods("setElevation", 1).get(0); assertEquals(21, SdkUtil.get().getMinApi(setElevation)); } @@ -45,7 +45,7 @@ public class SdkVersionTest { public void testCustomCode() { ModelClass view = ModelAnalyzer.getInstance() .findClass("android.databinding.tool.reflection.SdkVersionTest", null); - ModelMethod setElevation = view.getMethods("testCustomCode", 0)[0]; + ModelMethod setElevation = view.getMethods("testCustomCode", 0).get(0); assertEquals(1, SdkUtil.get().getMinApi(setElevation)); } @@ -53,7 +53,7 @@ public class SdkVersionTest { public void testSetForeground() { ModelClass view = ModelAnalyzer.getInstance() .findClass("android.widget.FrameLayout", null); - ModelMethod setForeground = view.getMethods("setForegroundGravity", 1)[0]; + ModelMethod setForeground = view.getMethods("setForegroundGravity", 1).get(0); assertEquals(1, SdkUtil.get().getMinApi(setForeground)); } } diff --git a/compiler/src/test/java/android/databinding/tool/reflection/java/JavaClass.java b/compiler/src/test/java/android/databinding/tool/reflection/java/JavaClass.java index 8b6bfaf6..b26e96a7 100644 --- a/compiler/src/test/java/android/databinding/tool/reflection/java/JavaClass.java +++ b/compiler/src/test/java/android/databinding/tool/reflection/java/JavaClass.java @@ -17,18 +17,20 @@ import android.databinding.tool.reflection.ModelClass; import android.databinding.tool.reflection.ModelField; import android.databinding.tool.reflection.ModelMethod; import android.databinding.tool.reflection.TypeUtil; +import org.jetbrains.annotations.NotNull; -import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class JavaClass extends ModelClass { - public final Class mClass; + final Class mClass; public JavaClass(Class clazz) { mClass = clazz; } + @NotNull @Override public String toJavaCode() { return toJavaCode(mClass); @@ -139,6 +141,7 @@ public class JavaClass extends ModelClass { return void.class.equals(mClass); } + @NotNull @Override public ModelClass unbox() { if (mClass.isPrimitive()) { @@ -167,6 +170,7 @@ public class JavaClass extends ModelClass { } + @NotNull @Override public JavaClass box() { if (!mClass.isPrimitive()) { @@ -197,6 +201,7 @@ public class JavaClass extends ModelClass { @Override public boolean isAssignableFrom(ModelClass that) { Class thatClass = ((JavaClass) that).mClass; + //noinspection unchecked return mClass.isAssignableFrom(thatClass); } @@ -208,48 +213,38 @@ public class JavaClass extends ModelClass { return new JavaClass(mClass.getSuperclass()); } + @NotNull @Override public String getCanonicalName() { return mClass.getCanonicalName(); } + @NotNull @Override public ModelClass erasure() { return this; } + @NotNull @Override public String getJniDescription() { return TypeUtil.getInstance().getDescription(this); } + @NotNull @Override - public ModelField[] getDeclaredFields() { - Field[] fields = mClass.getDeclaredFields(); - ModelField[] modelFields; - if (fields == null) { - modelFields = new ModelField[0]; - } else { - modelFields = new ModelField[fields.length]; - for (int i = 0; i < fields.length; i++) { - modelFields[i] = new JavaField(fields[i]); - } - } - return modelFields; + public List<ModelField> getDeclaredFields() { + return Stream.of(mClass.getDeclaredFields()) + .map(JavaField::new) + .collect(Collectors.toList()); } + @NotNull @Override - public ModelMethod[] getDeclaredMethods() { - Method[] methods = mClass.getDeclaredMethods(); - if (methods == null) { - return new ModelMethod[0]; - } else { - ModelMethod[] classMethods = new ModelMethod[methods.length]; - for (int i = 0; i < methods.length; i++) { - classMethods[i] = new JavaMethod(methods[i]); - } - return classMethods; - } + public List<ModelMethod> getDeclaredMethods() { + return Stream.of(mClass.getDeclaredMethods()) + .map(JavaMethod::new) + .collect(Collectors.toList()); } @Override |