summaryrefslogtreecommitdiff
path: root/compiler/src/main/java/android/databinding/tool/reflection
diff options
context:
space:
mode:
authorYigit Boyar <yboyar@google.com>2018-10-16 01:08:55 -0700
committerYigit Boyar <yboyar@google.com>2018-10-17 17:38:33 +0000
commit5cf6311da198837770582e5f6df9abe1582e4123 (patch)
treecd653aeeea11259562a4819bd190371ccf924277 /compiler/src/main/java/android/databinding/tool/reflection
parent797d08c2e629d3a4dbb460951e97cf06e86baf96 (diff)
downloaddata-binding-5cf6311da198837770582e5f6df9abe1582e4123.tar.gz
Move imports to a concrete class
This CL moves Map<String(alias), String(qname)> imports to a concrete ImportBag class. It is mostly a cleanup so that in a follow-up CL, we can start caching findClass calls based on available imports. Right now it is not possible since imports are all bloated with java.lang. This CL also stops adding all java.lang.* as static identifiers to every single model. Instead, it lazily registers it if an identifier expression cannot be found and name matches a java.lang class. Bug: 117808327 Test: ImportBagTest, existing tests pass Change-Id: Ideb41ab8cfc68aa4c7b55e84ffa218ba65558eb3
Diffstat (limited to 'compiler/src/main/java/android/databinding/tool/reflection')
-rw-r--r--compiler/src/main/java/android/databinding/tool/reflection/ImportBag.kt171
-rw-r--r--compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java2
-rw-r--r--compiler/src/main/java/android/databinding/tool/reflection/InjectedMethod.java4
-rw-r--r--compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java5
-rw-r--r--compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java9
5 files changed, 181 insertions, 10 deletions
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ImportBag.kt b/compiler/src/main/java/android/databinding/tool/reflection/ImportBag.kt
new file mode 100644
index 00000000..8b6fae1a
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/reflection/ImportBag.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.databinding.tool.reflection
+
+class MutableImportBag : ImportBag() {
+ open fun put(alias : String, qName : String) {
+ imports.putIfAbsent(alias, qName)
+ }
+}
+
+private class ImmutableImportBag : ImportBag() {
+
+}
+
+/**
+ * A class that can keep a list of imports and also run an equals check against itself.
+ *
+ * We do import everything in java.lang which is a waste of memory and killer for equals
+ * check. Instead, this class optimizes that part automatically.
+ *
+ * Equals on ImportBag is important because we resolve classes based on imports.
+ */
+sealed class ImportBag {
+ // alias to Import mapping
+ protected val imports = mutableMapOf<String, String>()
+
+ fun find(alias: String) : String? {
+ return imports[alias] ?: importJavaLang(alias)
+ }
+
+ fun contains(alias: String) = find(alias) != null
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other !is ImportBag) return false
+
+ if (imports != other.imports) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ return imports.hashCode()
+ }
+
+ companion object {
+ @JvmField
+ val EMPTY : ImportBag = ImmutableImportBag()
+ @JvmField
+ val JAVA_LANG_IMPORTS = setOf(
+ "Deprecated",
+ "Override",
+ "SafeVarargs",
+ "SuppressWarnings",
+ "Appendable",
+ "AutoCloseable",
+ "CharSequence",
+ "Cloneable",
+ "Comparable",
+ "Iterable",
+ "Readable",
+ "Runnable",
+ "Thread.UncaughtExceptionHandler",
+ "Boolean",
+ "Byte",
+ "Character",
+ "Character.Subset",
+ "Character.UnicodeBlock",
+ "Class",
+ "ClassLoader",
+ "Compiler",
+ "Double",
+ "Enum",
+ "Float",
+ "InheritableThreadLocal",
+ "Integer",
+ "Long",
+ "Math",
+ "Number",
+ "Object",
+ "Package",
+ "Process",
+ "ProcessBuilder",
+ "Runtime",
+ "RuntimePermission",
+ "SecurityManager",
+ "Short",
+ "StackTraceElement",
+ "StrictMath",
+ "String",
+ "StringBuffer",
+ "StringBuilder",
+ "System",
+ "Thread",
+ "ThreadGroup",
+ "ThreadLocal",
+ "Throwable",
+ "Void",
+ "Thread.State",
+ "ArithmeticException",
+ "ArrayIndexOutOfBoundsException",
+ "ArrayStoreException",
+ "ClassCastException",
+ "ClassNotFoundException",
+ "CloneNotSupportedException",
+ "EnumConstantNotPresentException",
+ "Exception",
+ "IllegalAccessException",
+ "IllegalArgumentException",
+ "IllegalMonitorStateException",
+ "IllegalStateException",
+ "IllegalThreadStateException",
+ "IndexOutOfBoundsException",
+ "InstantiationException",
+ "InterruptedException",
+ "NegativeArraySizeException",
+ "NoSuchFieldException",
+ "NoSuchMethodException",
+ "NullPointerException",
+ "NumberFormatException",
+ "ReflectiveOperationException",
+ "RuntimeException",
+ "SecurityException",
+ "StringIndexOutOfBoundsException",
+ "TypeNotPresentException",
+ "UnsupportedOperationException",
+ "AbstractMethodError",
+ "AssertionError",
+ "ClassCircularityError",
+ "ClassFormatError",
+ "Error",
+ "ExceptionInInitializerError",
+ "IllegalAccessError",
+ "IncompatibleClassChangeError",
+ "InstantiationError",
+ "InternalError",
+ "LinkageError",
+ "NoClassDefFoundError",
+ "NoSuchFieldError",
+ "NoSuchMethodError",
+ "OutOfMemoryError",
+ "StackOverflowError",
+ "ThreadDeath",
+ "UnknownError",
+ "UnsatisfiedLinkError",
+ "UnsupportedClassVersionError",
+ "VerifyError",
+ "VirtualMachineError"
+ )
+ private fun importJavaLang(alias : String) : String? {
+ return if (JAVA_LANG_IMPORTS.contains(alias)) {
+ "java.lang.$alias"
+ } else {
+ null
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java b/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java
index 45bedcb0..1ae22afa 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java
@@ -46,7 +46,7 @@ public class InjectedClass extends ModelClass {
mSuperClass = superClass;
}
- public void addVariable(String name, String type, Map<String, String> imports) {
+ public void addVariable(String name, String type, ImportBag imports) {
String capName = StringUtils.capitalize(name);
String setName = "set" + capName;
String getName = "get" + capName;
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/InjectedMethod.java b/compiler/src/main/java/android/databinding/tool/reflection/InjectedMethod.java
index be1f8d79..0a9f3ce5 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/InjectedMethod.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/InjectedMethod.java
@@ -31,13 +31,13 @@ public class InjectedMethod extends ModelMethod {
private final String mName;
private final String mReturnTypeName;
private final String[] mParameterTypeNames;
- private final Map<String, String> mImports;
+ private final ImportBag mImports;
private ModelClass[] mParameterTypes;
private ModelClass mReturnType;
private boolean mIsStatic;
public InjectedMethod(InjectedClass containingClass, boolean isStatic, String name,
- Map<String, String> imports, String returnType, String... parameters) {
+ ImportBag imports, String returnType, String... parameters) {
mContainingClass = containingClass;
mName = name;
mIsStatic = isStatic;
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java b/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java
index f650b9c5..0671165d 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java
@@ -19,7 +19,6 @@ import android.databinding.tool.Context;
import android.databinding.tool.LibTypes;
import android.databinding.tool.util.L;
import android.databinding.tool.util.Preconditions;
-import com.android.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
@@ -251,14 +250,14 @@ public abstract class ModelAnalyzer {
return "null";
}
- public final ModelClass findClass(String className, Map<String, String> imports) {
+ public final ModelClass findClass(String className, ImportBag imports) {
if (mInjectedClasses.containsKey(className)) {
return mInjectedClasses.get(className);
}
return findClassInternal(className, imports);
}
- public abstract ModelClass findClassInternal(String className, Map<String, String> imports);
+ public abstract ModelClass findClassInternal(String className, ImportBag importBag);
public abstract ModelClass findClass(Class classType);
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java
index 7ef7585c..ec7b872e 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java
@@ -16,6 +16,7 @@
package android.databinding.tool.reflection.annotation;
import android.databinding.tool.LibTypes;
+import android.databinding.tool.reflection.ImportBag;
import android.databinding.tool.reflection.ModelAnalyzer;
import android.databinding.tool.reflection.ModelClass;
import android.databinding.tool.reflection.TypeUtil;
@@ -71,7 +72,7 @@ public class AnnotationAnalyzer extends ModelAnalyzer {
}
@Override
- public ModelClass findClassInternal(String className, Map<String, String> imports) {
+ public ModelClass findClassInternal(String className, ImportBag imports) {
className = className.trim();
int numDimensions = 0;
while (className.endsWith("[]")) {
@@ -130,12 +131,12 @@ public class AnnotationAnalyzer extends ModelAnalyzer {
return new AnnotationClass(type);
}
- private TypeElement getTypeElement(String className, Map<String, String> imports) {
+ private TypeElement getTypeElement(String className, ImportBag imports) {
Elements elementUtils = getElementUtils();
final boolean hasDot = className.indexOf('.') >= 0;
if (!hasDot && imports != null) {
// try the imports
- String importedClass = imports.get(className);
+ String importedClass = imports.find(className);
if (importedClass != null) {
className = importedClass;
}
@@ -177,7 +178,7 @@ public class AnnotationAnalyzer extends ModelAnalyzer {
}
private ArrayList<String> splitTemplateParameters(String templateParameters) {
- ArrayList<String> list = new ArrayList<String>();
+ ArrayList<String> list = new ArrayList<>();
int index = 0;
int openCount = 0;
StringBuilder arg = new StringBuilder();