diff --git a/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java b/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java index 3b5e3150380a0..cc89e35d4b9e3 100644 --- a/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java +++ b/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Set; import javax.annotation.processing.AbstractProcessor; @@ -23,11 +24,14 @@ import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeKind; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; import javax.tools.Diagnostic; import javax.tools.FileObject; import javax.tools.JavaFileObject; diff --git a/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessExpressions.java b/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessExpressions.java new file mode 100644 index 0000000000000..a1ae692c637b3 --- /dev/null +++ b/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessExpressions.java @@ -0,0 +1,43 @@ +package com.android.databinding.annotationprocessor; + +import android.binding.Bindable; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.io.Writer; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.tools.Diagnostic; +import javax.tools.FileObject; +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; + +public class ProcessExpressions { + + public static boolean process(ProcessingEnvironment processingEnv, + Set annotations, RoundEnvironment roundEnv) { + return true; + } +} diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/Binding.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/Binding.java index 82e440c122046..d1740cce8bf5e 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/Binding.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/Binding.java @@ -16,6 +16,8 @@ package com.android.databinding; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import com.android.databinding.store.SetterStore; import com.android.databinding.expr.Expr; @@ -37,15 +39,15 @@ public class Binding { } public String toJavaCode(String targetViewName, String expressionCode) { - Class viewType = mTarget.getResolvedType(); - return SetterStore.get(ClassAnalyzer.getInstance()).getSetterCall(mName, viewType, + ReflectionClass viewType = mTarget.getResolvedType(); + return SetterStore.get(ReflectionAnalyzer.getInstance()).getSetterCall(mName, viewType, mExpr.getResolvedType(), targetViewName, expressionCode); } -// private String resolveJavaCode(ClassAnalyzer classAnalyzer) { +// private String resolveJavaCode(ReflectionAnalyzer reflectionAnalyzer) { // // } -//// return classAnalyzer.findMethod(mTarget.getResolvedType(), mName, +//// return reflectionAnalyzer.findMethod(mTarget.getResolvedType(), mName, //// Arrays.asList(mExpr.getResolvedType())); // //} // diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/BindingTarget.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/BindingTarget.java index ab0b34c29ec92..58b8de5f1d860 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/BindingTarget.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/BindingTarget.java @@ -18,8 +18,8 @@ package com.android.databinding; import com.android.databinding.expr.Expr; import com.android.databinding.expr.ExprModel; - -import org.w3c.dom.Node; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import java.util.ArrayList; import java.util.List; @@ -29,7 +29,7 @@ public class BindingTarget { String mViewClass; List mBindings = new ArrayList<>(); ExprModel mModel; - Class mResolvedClass; + ReflectionClass mResolvedClass; String mIncludedLayout; // if this target presents itself in multiple layout files with different view types, // it receives an interface type and should use it in the getter instead. @@ -68,9 +68,9 @@ public class BindingTarget { return mViewClass; } - public Class getResolvedType() { + public ReflectionClass getResolvedType() { if (mResolvedClass == null) { - mResolvedClass = ClassAnalyzer.getInstance().findClass(mViewClass); + mResolvedClass = ReflectionAnalyzer.getInstance().findClass(mViewClass); } return mResolvedClass; } diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/ExpressionVisitor.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/ExpressionVisitor.java index abedbd25dad3c..1b5459d349b35 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/ExpressionVisitor.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/ExpressionVisitor.java @@ -20,6 +20,7 @@ import com.google.common.base.Preconditions; import com.android.databinding.expr.Expr; import com.android.databinding.expr.ExprModel; +import com.android.databinding.reflection.ReflectionAnalyzer; import org.antlr.v4.runtime.misc.NotNull; import org.antlr.v4.runtime.tree.ParseTree; @@ -78,32 +79,38 @@ public class ExpressionVisitor extends BindingExpressionBaseVisitor { @Override public Expr visitQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx) { final Expr left = ctx.left.accept(this); - return mModel.ternary( - mModel.comparison("==", left, mModel.symbol("null", Object.class)), + return mModel.ternary(mModel.comparison("==", left, mModel.symbol("null", Object.class)), left, ctx.right.accept(this)); } @Override public Expr visitTerminal(@NotNull TerminalNode node) { final int type = node.getSymbol().getType(); + Class classType; switch (type) { case BindingExpressionParser.IntegerLiteral: - return mModel.symbol(node.getText(), Integer.class); + classType = int.class; + break; case BindingExpressionParser.FloatingPointLiteral: - return mModel.symbol(node.getText(), Float.class); + classType = float.class; + break; case BindingExpressionParser.BooleanLiteral: - return mModel.symbol(node.getText(), Boolean.class); + classType = boolean.class; + break; case BindingExpressionParser.CharacterLiteral: - return mModel.symbol(node.getText(), Character.class); + classType = char.class; + break; case BindingExpressionParser.SingleQuoteString: - return mModel.symbol(node.getText(), String.class); case BindingExpressionParser.DoubleQuoteString: - return mModel.symbol(node.getText(), String.class); + classType = String.class; + break; case BindingExpressionParser.NullLiteral: - return mModel.symbol(node.getText(), Object.class); + classType = Object.class; + break; default: throw new RuntimeException("cannot create expression from terminal node " + node.toString()); } + return mModel.symbol(node.getText(), classType); } @Override @@ -234,8 +241,8 @@ public class ExpressionVisitor extends BindingExpressionBaseVisitor { // @org.jetbrains.annotations.NotNull // @Override // public Class resolveValueType( -// @org.jetbrains.annotations.NotNull ClassAnalyzer classAnalyzer) { -// return classAnalyzer.commonParentOf(aggregate.getResolvedClass(), nextResult.getResolvedClass()); +// @org.jetbrains.annotations.NotNull ReflectionAnalyzer reflectionAnalyzer) { +// return reflectionAnalyzer.commonParentOf(aggregate.getResolvedClass(), nextResult.getResolvedClass()); // } // // @org.jetbrains.annotations.NotNull diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/BracketExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/BracketExpr.java index b576554475c58..06cc7c10cfbbb 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/BracketExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/BracketExpr.java @@ -16,7 +16,9 @@ package com.android.databinding.expr; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ClassClass; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import java.util.List; import java.util.Map; @@ -36,24 +38,20 @@ public class BracketExpr extends Expr { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { - Class targetType = getTarget().resolveType(classAnalyzer); + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { + ReflectionClass targetType = getTarget().resolveType(reflectionAnalyzer); if (targetType.isArray()) { mAccessor = BracketAccessor.ARRAY; - } else if (List.class.isAssignableFrom(targetType)) { + } else if (targetType.isList()) { mAccessor = BracketAccessor.LIST; - } else if (Map.class.isAssignableFrom(targetType)) { + } else if (targetType.isMap()) { mAccessor = BracketAccessor.MAP; } else { throw new IllegalArgumentException("Cannot determine variable type used in [] " + "expression. Cast the value to List, ObservableList, Map, " + "Cursor, or array."); } - if (targetType.isArray()) { - return targetType.getComponentType(); - } else { - return Object.class; - } + return targetType.getComponentType(); } @Override diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ComparisonExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ComparisonExpr.java index 82b00357a1ed1..2737e31fc61c3 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ComparisonExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ComparisonExpr.java @@ -16,7 +16,8 @@ package com.android.databinding.expr; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import java.util.List; @@ -33,8 +34,8 @@ public class ComparisonExpr extends Expr { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { - return boolean.class; + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { + return reflectionAnalyzer.loadPrimitive("boolean"); } @Override diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/Expr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/Expr.java index d4821fe3da94b..7e597339cdc76 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/Expr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/Expr.java @@ -28,8 +28,8 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import com.android.databinding.ClassAnalyzer; -import com.android.databinding.util.L; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; abstract public class Expr { @@ -41,7 +41,7 @@ abstract public class Expr { private Boolean mIsDynamic; - private Class mResolvedType; + private ReflectionClass mResolvedType; private String mUniqueKey; @@ -145,7 +145,7 @@ abstract public class Expr { } public boolean isObservable() { - return ClassAnalyzer.getInstance().isObservable(getResolvedType()); + return ReflectionAnalyzer.getInstance().isObservable(getResolvedType()); } public BitSet getShouldReadFlags() { @@ -278,15 +278,15 @@ abstract public class Expr { } - public Class getResolvedType() { + public ReflectionClass getResolvedType() { if (mResolvedType == null) { // TODO not get instance - mResolvedType = resolveType(ClassAnalyzer.getInstance()); + mResolvedType = resolveType(ReflectionAnalyzer.getInstance()); } return mResolvedType; } - abstract protected Class resolveType(ClassAnalyzer classAnalyzer); + abstract protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer); abstract protected List constructDependencies(); @@ -535,7 +535,7 @@ abstract public class Expr { } public String getDefaultValue() { - return ClassAnalyzer.getInstance().getDefaultValue(getResolvedType().getSimpleName()); + return ReflectionAnalyzer.getInstance().getDefaultValue(getResolvedType().toJavaCode()); } protected BitSet getPredicateInvalidFlags() { @@ -569,7 +569,7 @@ abstract public class Expr { return mIsUsed; } - public void updateExpr(ClassAnalyzer classAnalyzer) { + public void updateExpr(ReflectionAnalyzer reflectionAnalyzer) { } static class Node { diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ExprModel.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ExprModel.java index 9da08a7cd4f53..4a0d7fd96e4eb 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ExprModel.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ExprModel.java @@ -21,7 +21,8 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import com.android.databinding.util.L; import com.android.databinding.writer.FlagSet; @@ -191,7 +192,7 @@ public class ExprModel { public void seal() { List notifiableExpressions = new ArrayList<>(); //ensure class analyzer. We need to know observables at this point - final ClassAnalyzer classAnalyzer = ClassAnalyzer.getInstance(); + final ReflectionAnalyzer reflectionAnalyzer = ReflectionAnalyzer.getInstance(); ArrayList processedExprs = new ArrayList<>(); ArrayList exprs = new ArrayList<>(); @@ -200,13 +201,13 @@ public class ExprModel { exprs.addAll(mExprMap.values()); exprs.removeAll(processedExprs); for (Expr expr: exprs) { - expr.updateExpr(classAnalyzer); + expr.updateExpr(reflectionAnalyzer); } processedExprs.addAll(exprs); } while (!exprs.isEmpty()); int counter = 0; - final Iterable observables = filterObservables(classAnalyzer); + final Iterable observables = filterObservables(reflectionAnalyzer); List flagMapping = Lists.newArrayList(); mObservables = Lists.newArrayList(); for (Expr expr : observables) { @@ -219,7 +220,7 @@ public class ExprModel { } // non-observable identifiers gets next ids - final Iterable nonObservableIds = filterNonObservableIds(classAnalyzer); + final Iterable nonObservableIds = filterNonObservableIds(reflectionAnalyzer); for (Expr expr : nonObservableIds) { flagMapping.add(expr.getUniqueKey()); expr.setId(counter++); @@ -336,23 +337,23 @@ public class ExprModel { return mFlagMapping[id]; } - private Iterable filterNonObservableIds(final ClassAnalyzer classAnalyzer) { + private Iterable filterNonObservableIds(final ReflectionAnalyzer reflectionAnalyzer) { return Iterables.filter(mExprMap.values(), new Predicate() { @Override public boolean apply(Expr input) { return input instanceof IdentifierExpr && !input.hasId() - && !classAnalyzer.isObservable(input.getResolvedType()) + && !reflectionAnalyzer.isObservable(input.getResolvedType()) && input.isDynamic(); } }); } - private Iterable filterObservables(final ClassAnalyzer classAnalyzer) { + private Iterable filterObservables(final ReflectionAnalyzer reflectionAnalyzer) { return Iterables.filter(mExprMap.values(), new Predicate() { @Override public boolean apply(Expr input) { - return classAnalyzer.isObservable(input.getResolvedType()); + return reflectionAnalyzer.isObservable(input.getResolvedType()); } }); } diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/FieldAccessExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/FieldAccessExpr.java index efb8cdf8466e3..5e63971e5d2e6 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/FieldAccessExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/FieldAccessExpr.java @@ -16,18 +16,16 @@ package com.android.databinding.expr; -import com.android.databinding.ClassAnalyzer; -import com.android.databinding.util.L; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.Callable; +import com.android.databinding.reflection.ReflectionClass; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.Collections; import java.util.List; public class FieldAccessExpr extends Expr { String mName; - ClassAnalyzer.Callable mGetter; + Callable mGetter; final boolean mIsObservableField; FieldAccessExpr(Expr parent, String name) { @@ -46,7 +44,7 @@ public class FieldAccessExpr extends Expr { return getChildren().get(0); } - public ClassAnalyzer.Callable getGetter() { + public Callable getGetter() { if (mGetter == null) { getResolvedType(); } @@ -62,7 +60,7 @@ public class FieldAccessExpr extends Expr { getResolvedType(); } // maybe this is just a final field in which case cannot be notified as changed - return mGetter.type != ClassAnalyzer.Callable.Type.FIELD || mGetter.isDynamic; + return mGetter.type != Callable.Type.FIELD || mGetter.isDynamic; } @Override @@ -89,10 +87,10 @@ public class FieldAccessExpr extends Expr { } @Override - public void updateExpr(ClassAnalyzer classAnalyzer) { + public void updateExpr(ReflectionAnalyzer reflectionAnalyzer) { if (mGetter == null) { - mGetter = classAnalyzer.findMethodOrField(mChildren.get(0).getResolvedType(), mName); - if (classAnalyzer.isObservableField(mGetter.resolvedType)) { + mGetter = reflectionAnalyzer.findMethodOrField(mChildren.get(0).getResolvedType(), mName); + if (reflectionAnalyzer.isObservableField(mGetter.resolvedType)) { // Make this the ".get()" and add an extra field access for the observable field Expr parent = getParent(); parent.getParents().remove(this); @@ -103,16 +101,16 @@ public class FieldAccessExpr extends Expr { getChildren().add(observableField); observableField.getParents().add(this); - mGetter = classAnalyzer.findMethodOrField(mGetter.resolvedType, "get"); + mGetter = reflectionAnalyzer.findMethodOrField(mGetter.resolvedType, "get"); mName = ""; } } } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { if (mGetter == null) { - mGetter = classAnalyzer.findMethodOrField(mChildren.get(0).getResolvedType(), mName); + mGetter = reflectionAnalyzer.findMethodOrField(mChildren.get(0).getResolvedType(), mName); } return mGetter.resolvedType; } diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/GroupExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/GroupExpr.java index b5ef3cea21da9..d62b98cf1c7ce 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/GroupExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/GroupExpr.java @@ -16,7 +16,8 @@ package com.android.databinding.expr; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import java.util.List; @@ -26,8 +27,8 @@ public class GroupExpr extends Expr { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { - return getWrapped().resolveType(classAnalyzer); + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { + return getWrapped().resolveType(reflectionAnalyzer); } @Override diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/IdentifierExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/IdentifierExpr.java index a123a8017dec8..6e9485110f82a 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/IdentifierExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/IdentifierExpr.java @@ -19,7 +19,8 @@ package com.android.databinding.expr; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import java.util.List; @@ -57,10 +58,10 @@ public class IdentifierExpr extends Expr { } @Override - protected Class resolveType(final ClassAnalyzer classAnalyzer) { + protected ReflectionClass resolveType(final ReflectionAnalyzer reflectionAnalyzer) { Preconditions.checkNotNull(mUserDefinedType, "Identifiers must have user defined types from the XML file. %s is missing it", mName); - return classAnalyzer.findClass(mUserDefinedType); + return reflectionAnalyzer.findClass(mUserDefinedType); } @Override diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/MathExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/MathExpr.java index e14a1433a27f6..7d99a58e87013 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/MathExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/MathExpr.java @@ -16,7 +16,8 @@ package com.android.databinding.expr; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import java.util.List; @@ -33,15 +34,15 @@ public class MathExpr extends Expr { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { if ("+".equals(mOp)) { // TODO we need upper casting etc. - if (String.class.equals(getLeft().getResolvedType()) - || String.class.equals(getRight().getResolvedType())) { - return String.class; + if (getLeft().getResolvedType().isString() + || getRight().getResolvedType().isString()) { + return reflectionAnalyzer.findClass(String.class); } } - return classAnalyzer.findCommonParentOf(getLeft().getResolvedType(), + return reflectionAnalyzer.findCommonParentOf(getLeft().getResolvedType(), getRight().getResolvedType()); } diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/MethodCallExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/MethodCallExpr.java index 5ed387ebd117c..119e65e919bb4 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/MethodCallExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/MethodCallExpr.java @@ -18,7 +18,9 @@ package com.android.databinding.expr; import com.google.common.collect.Iterables; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.Callable; +import com.android.databinding.reflection.ReflectionClass; import java.util.ArrayList; import java.util.Arrays; @@ -27,7 +29,7 @@ import java.util.List; public class MethodCallExpr extends Expr { final String mName; - ClassAnalyzer.Callable mGetter; + Callable mGetter; MethodCallExpr(Expr target, String name, List args) { super(Iterables.concat(Arrays.asList(target), args)); @@ -35,13 +37,13 @@ public class MethodCallExpr extends Expr { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { if (mGetter == null) { - List args = new ArrayList<>(); + List args = new ArrayList<>(); for (Expr expr : getArgs()) { args.add(expr.getResolvedType()); } - mGetter = classAnalyzer.findMethod(getTarget().getResolvedType(), mName, args); + mGetter = reflectionAnalyzer.findMethod(getTarget().getResolvedType(), mName, args); } return mGetter.resolvedType; } @@ -75,7 +77,7 @@ public class MethodCallExpr extends Expr { return getChildren().subList(1, getChildren().size()); } - public ClassAnalyzer.Callable getGetter() { + public Callable getGetter() { return mGetter; } } diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ResourceExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ResourceExpr.java index 80cbbf5ab9d3f..a8caace564b4b 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ResourceExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/ResourceExpr.java @@ -17,12 +17,10 @@ package com.android.databinding.expr; import com.google.common.collect.ImmutableMap; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; -import java.io.IOException; -import java.net.URL; import java.util.Collections; -import java.util.Enumeration; import java.util.List; import java.util.Map; @@ -62,7 +60,7 @@ public class ResourceExpr extends Expr { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { String type; switch (mResourceType) { case "anim": @@ -72,43 +70,36 @@ public class ResourceExpr extends Expr { type = "android.animation.Animator"; break; case "bool": - return boolean.class; + return reflectionAnalyzer.findClass(boolean.class); case "color": - return int.class; + case "dimenOffset": + case "dimenSize": + case "id": + case "integer": + case "layout": + case "plurals": + return reflectionAnalyzer.findClass(int.class); case "colorStateList": type = "android.content.res.ColorStateList"; break; case "dimen": - return float.class; - case "dimenOffset": - return int.class; - case "dimenSize": - return int.class; + case "fraction": + return reflectionAnalyzer.findClass(float.class); case "drawable": type = "android.graphics.drawable.Drawable"; break; - case "fraction": - return float.class; - case "id": - return int.class; case "intArray": - return int[].class; - case "integer": - return int.class; + return reflectionAnalyzer.findClass(int[].class); case "interpolator": type = ""; break; - case "layout": - return int.class; - case "plurals": - return int.class; case "stateListAnimator": type = "android.animation.StateListAnimator"; break; case "string": - return String.class; + return reflectionAnalyzer.findClass(String.class); case "stringArray": - return String[].class; + return reflectionAnalyzer.findClass(String[].class); case "transition": type = "android.transition.Transition"; break; @@ -119,7 +110,7 @@ public class ResourceExpr extends Expr { type = mResourceType; break; } - return classAnalyzer.findClass(type); + return reflectionAnalyzer.findClass(type); } @Override diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/SymbolExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/SymbolExpr.java index 86299c63d96f9..5c66822a85e9b 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/SymbolExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/SymbolExpr.java @@ -18,7 +18,8 @@ package com.android.databinding.expr; import com.google.common.collect.Lists; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import java.util.List; @@ -37,8 +38,8 @@ public class SymbolExpr extends Expr { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { - return mType; + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { + return reflectionAnalyzer.findClass(mType); } @Override diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/TernaryExpr.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/TernaryExpr.java index fc25e6d41a8a7..01dde253ec214 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/TernaryExpr.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/expr/TernaryExpr.java @@ -18,7 +18,8 @@ package com.android.databinding.expr; import com.google.common.collect.Lists; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; import java.util.BitSet; import java.util.List; @@ -46,8 +47,8 @@ public class TernaryExpr extends Expr { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { - return classAnalyzer.findCommonParentOf(getIfTrue().getResolvedType(), + protected ReflectionClass resolveType(ReflectionAnalyzer reflectionAnalyzer) { + return reflectionAnalyzer.findCommonParentOf(getIfTrue().getResolvedType(), getIfFalse().getResolvedType()); } diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/Callable.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/Callable.java new file mode 100644 index 0000000000000..75c1e035fa223 --- /dev/null +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/Callable.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 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 com.android.databinding.reflection; + +public class Callable { + + public static enum Type { + METHOD, + FIELD + } + + public final Type type; + + public final String name; + + public final ReflectionClass resolvedType; + + public final boolean isDynamic; + + public final boolean canBeInvalidated; + + public Callable(Type type, String name, ReflectionClass resolvedType, boolean isDynamic, + boolean canBeInvalidated) { + this.type = type; + this.name = name; + this.resolvedType = resolvedType; + this.isDynamic = isDynamic; + this.canBeInvalidated = canBeInvalidated; + } + + public String getTypeCodeName() { + return resolvedType.toJavaCode(); + } + + @Override + public String toString() { + return "Callable{" + + "type=" + type + + ", name='" + name + '\'' + + ", resolvedType=" + resolvedType + + ", isDynamic=" + isDynamic + + ", canBeInvalidated=" + canBeInvalidated + + '}'; + } +} diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassAnalyzer.java similarity index 71% rename from tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java rename to tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassAnalyzer.java index e590fb27706c8..ff1ccb5f56ccc 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassAnalyzer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.databinding; +package com.android.databinding.reflection; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; @@ -24,14 +24,18 @@ import com.android.databinding.util.L; import org.apache.commons.lang3.StringUtils; +import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; -public class ClassAnalyzer { +public class ClassAnalyzer extends ReflectionAnalyzer { private static final String OBSERVABLE_CLASS_NAME = "android.binding.Observable"; private static final String OBSERVABLE_LIST_CLASS_NAME = "android.binding.ObservableList"; @@ -62,7 +66,7 @@ public class ClassAnalyzer { private static ClassLoader sClassLoader; - private HashMap mClassCache = new HashMap<>(); + private HashMap mClassCache = new HashMap<>(); private final ClassLoader mClassLoader; @@ -124,22 +128,27 @@ public class ClassAnalyzer { return name; } - public boolean isDataBinder(Class klass) { - return mIViewDataBinder.isAssignableFrom(klass); + @Override + public boolean isDataBinder(ReflectionClass reflectionClass) { + ClassClass classClass = (ClassClass) reflectionClass; + return mIViewDataBinder.isAssignableFrom(classClass.mClass); } - static String toCodeName(Class klass) { - return klass.getName().replace("$", "."); - } - - public Callable findMethod(Class klass, String name, List args) { + @Override + public Callable findMethod(ReflectionClass reflectionClass, String name, + List argClasses) { + Class klass = ((ClassClass) reflectionClass).mClass; + ArrayList args = new ArrayList<>(argClasses.size()); + for (int i = 0; i < argClasses.size(); i++) { + args.add(((ClassClass) argClasses.get(i)).mClass); + } // TODO implement properly for (String methodName : new String[]{"set" + StringUtils.capitalize(name), name}) { for (Method method : klass.getMethods()) { if (methodName.equals(method.getName()) && args.size() == method .getParameterTypes().length) { - return new Callable(Callable.Type.METHOD, methodName, method.getReturnType(), true, - false); + return new Callable(Callable.Type.METHOD, methodName, + new ClassClass(method.getReturnType()), true, false); } } } @@ -148,12 +157,20 @@ public class ClassAnalyzer { "cannot find method " + name + " at class " + klass.getSimpleName()); } - public boolean isObservable(Class klass) { - return mObservable.isAssignableFrom(klass) || mObservableList.isAssignableFrom(klass) || - mObservableMap.isAssignableFrom(klass); + @Override + public boolean isObservable(ReflectionClass reflectionClass) { + Class klass = ((ClassClass) reflectionClass).mClass; + return isObservable(klass); } - public boolean isObservableField(Class klass) { + private boolean isObservable(Class klass) { + return mObservable.isAssignableFrom(klass) || mObservableList.isAssignableFrom(klass) || + mObservableMap.isAssignableFrom(klass); + } + + @Override + public boolean isObservableField(ReflectionClass reflectionClass) { + Class klass = ((ClassClass) reflectionClass).mClass; for (Class observableField : mObservableFields) { if (observableField.isAssignableFrom(klass)) { return true; @@ -162,16 +179,29 @@ public class ClassAnalyzer { return false; } - public boolean isBindable(Field field) { + @Override + public boolean isBindable(ReflectionField reflectionField) { + Field field = ((ClassField) reflectionField).mField; + return isBindable(field); + } + + @Override + public boolean isBindable(ReflectionMethod reflectionMethod) { + Method method = ((ClassMethod) reflectionMethod).mMethod; + return isBindable(method); + } + + private boolean isBindable(Field field) { return field.getAnnotation(mBindable) != null; } - public boolean isBindable(Method method) { + private boolean isBindable(Method method) { return method.getAnnotation(mBindable) != null; } - public Callable findMethodOrField(Class klass, String name) { - + @Override + public Callable findMethodOrField(ReflectionClass reflectionClass, String name) { + Class klass = ((ClassClass) reflectionClass).mClass; for (String methodName : new String[]{"get" + StringUtils.capitalize(name), "is" + StringUtils.capitalize(name), name}) { @@ -180,9 +210,8 @@ public class ClassAnalyzer { Field backingField = findField(klass, name, true); if (Modifier.isPublic(method.getModifiers())) { final Callable result = new Callable(Callable.Type.METHOD, methodName, - method.getReturnType(), - true, isBindable(method) || (backingField != null && isBindable( - backingField))); + new ClassClass(method.getReturnType()), true, + isBindable(method) || (backingField != null && isBindable(backingField)) ); L.d("backing field for %s is %s", result, backingField); return result; } @@ -193,9 +222,9 @@ public class ClassAnalyzer { try { Field field = findField(klass, name, false); if (Modifier.isPublic(field.getModifiers())) { - return new Callable(Callable.Type.FIELD, name, field.getType(), + return new Callable(Callable.Type.FIELD, name, new ClassClass(field.getType()), !Modifier.isFinal(field.getModifiers()) - || isObservable(field.getType()), isBindable(field)); + || isObservable(field.getType()), isBindable(field)); } } catch (Throwable t) { @@ -247,14 +276,18 @@ public class ClassAnalyzer { return findField(klass, name, false); } - public Class findCommonParentOf(Class klass1, Class klass2) { - Class curr = klass1; + @Override + public ReflectionClass findCommonParentOf(ReflectionClass reflectionClass1, + ReflectionClass reflectionClass2) { + ClassClass klass1 = (ClassClass) reflectionClass1; + ClassClass klass2 = (ClassClass) reflectionClass2; + ClassClass curr = klass1; while (curr != null && !curr.isAssignableFrom(klass2)) { curr = curr.getSuperclass(); } if (curr == null) { - Class primitive1 = SetterStore.getPrimitiveType(klass1); - Class primitive2 = SetterStore.getPrimitiveType(klass2); + ClassClass primitive1 = klass1.unbox(); + ClassClass primitive2 = klass2.unbox(); if (!klass1.equals(primitive1) || !klass2.equals(primitive2)) { return findCommonParentOf(primitive1, primitive2); } @@ -264,62 +297,31 @@ public class ClassAnalyzer { return curr; } - public ClassLoader getClassLoader() { - return mClassLoader; - } - - public Class loadPrimitive(String className) { + public ClassClass loadPrimitive(String className) { if ("int".equals(className)) { - return int.class; + return new ClassClass(int.class); } if ("short".equals(className)) { - return short.class; + return new ClassClass(short.class); } if ("long".equals(className)) { - return long.class; + return new ClassClass(long.class); } if ("float".equals(className)) { - return float.class; + return new ClassClass(float.class); } if ("double".equals(className)) { - return double.class; + return new ClassClass(double.class); } if ("boolean".equals(className) || "bool".equals(className)) { - return boolean.class; + return new ClassClass(boolean.class); } return null; } - public String getDefaultValue(String className) { - if("int".equals(className)) { - return "0"; - } - if("short".equals(className)) { - return "0"; - } - if("long".equals(className)) { - return "0L"; - } - if("float".equals(className)) { - return "0f"; - } - if("double".equals(className)) { - return "0.0"; - } - if("boolean".equals(className)) { - return "false"; - } - if ("char".equals(className)) { - return "'\\u0000'"; - } - if ("byte".equals(className)) { - return "0"; - } - return "null"; - } - - public Class findClass(String className) { - Class loaded = mClassCache.get(className); + @Override + public ClassClass findClass(String className) { + ClassClass loaded = mClassCache.get(className); if (loaded != null) { return loaded; } @@ -329,11 +331,11 @@ public class ClassAnalyzer { try { if (className.startsWith("[") && className.contains("L")) { int indexOfL = className.indexOf('L'); - Class baseClass = findClass( + ClassClass baseClass = findClass( className.substring(indexOfL + 1, className.length() - 1)); String realClassName = className.substring(0, indexOfL + 1) + - baseClass.getCanonicalName() + ';'; - loaded = Class.forName(realClassName, false, mClassLoader); + baseClass.mClass.getCanonicalName() + ';'; + loaded = new ClassClass(Class.forName(realClassName, false, mClassLoader)); mClassCache.put(className, loaded); } else { loaded = loadRecursively(className); @@ -345,14 +347,24 @@ public class ClassAnalyzer { } } Preconditions.checkNotNull(loaded, "Tried to load " + className + " but could not find :/"); - L.d("loaded class %s", loaded.getCanonicalName()); + L.d("loaded class %s", loaded.mClass.getCanonicalName()); return loaded; } - public Class loadRecursively(String className) throws ClassNotFoundException { + @Override + public boolean isNullable(ReflectionClass reflectionClass) { + return false; + } + + @Override + public ReflectionClass findClass(Class classType) { + return new ClassClass(classType); + } + + private ClassClass loadRecursively(String className) throws ClassNotFoundException { try { L.d("recursively checking %s", className); - return mClassLoader.loadClass(className); + return new ClassClass(mClassLoader.loadClass(className)); } catch (ClassNotFoundException ex) { int lastIndexOfDot = className.lastIndexOf("."); if (lastIndexOfDot == -1) { @@ -370,50 +382,20 @@ public class ClassAnalyzer { } } - public static boolean isNullable(Class klass) { - return Object.class.isAssignableFrom(klass); - } - - - public static class Callable { - - public static enum Type { - METHOD, - FIELD - } - - public final Type type; - - public final String name; - - public final Class resolvedType; - - public final boolean isDynamic; - - public final boolean canBeInvalidated; - - public Callable(Type type, String name, Class resolvedType, boolean isDynamic, - boolean canBeInvalidated) { - this.type = type; - this.name = name; - this.resolvedType = resolvedType; - this.isDynamic = isDynamic; - this.canBeInvalidated = canBeInvalidated; - } - - public String getTypeCodeName() { - return ClassAnalyzer.toCodeName(resolvedType); - } - - @Override - public String toString() { - return "Callable{" + - "type=" + type + - ", name='" + name + '\'' + - ", resolvedType=" + resolvedType + - ", isDynamic=" + isDynamic + - ", canBeInvalidated=" + canBeInvalidated + - '}'; + @Override + public List getResources(String name) { + List urlList = new ArrayList(); + Enumeration urls = null; + try { + urls = mClassLoader.getResources(name); + if (urls != null) { + while (urls.hasMoreElements()) { + urlList.add(urls.nextElement()); + } + } + } catch (IOException e) { + e.printStackTrace(); } + return urlList; } } diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassClass.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassClass.java new file mode 100644 index 0000000000000..2ffa0e7c04512 --- /dev/null +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassClass.java @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2015 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 com.android.databinding.reflection; + +import java.lang.reflect.Method; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; + +public class ClassClass implements ReflectionClass { + + public final Class mClass; + + public ClassClass(Class clazz) { + mClass = clazz; + } + + @Override + public String toJavaCode() { + return toJavaCode(mClass); + } + + private static String toJavaCode(Class aClass) { + if (aClass.isArray()) { + Class component = aClass.getComponentType(); + return toJavaCode(component) + "[]"; + } else { + return aClass.getCanonicalName().replace('$', '.'); + } + } + + @Override + public boolean isArray() { + return mClass.isArray(); + } + + @Override + public ClassClass getComponentType() { + if (mClass.isArray()) { + return new ClassClass(mClass.getComponentType()); + } else if (isList() || isMap()) { + return new ClassClass(Object.class); + } else { + return null; + } + } + + @Override + public boolean isList() { + return List.class.isAssignableFrom(mClass); + } + + @Override + public boolean isMap() { + return Map.class.isAssignableFrom(mClass); + } + + @Override + public boolean isString() { + return String.class.equals(mClass); + } + + @Override + public boolean isNullable() { + return Object.class.isAssignableFrom(mClass); + } + + @Override + public boolean isPrimitive() { + return mClass.isPrimitive(); + } + + @Override + public boolean isBoolean() { + return boolean.class.equals(mClass); + } + + @Override + public boolean isChar() { + return char.class.equals(mClass); + } + + @Override + public boolean isByte() { + return byte.class.equals(mClass); + } + + @Override + public boolean isShort() { + return short.class.equals(mClass); + } + + @Override + public boolean isInt() { + return int.class.equals(mClass); + } + + @Override + public boolean isLong() { + return long.class.equals(mClass); + } + + @Override + public boolean isFloat() { + return float.class.equals(mClass); + } + + @Override + public boolean isDouble() { + return double.class.equals(mClass); + } + + @Override + public boolean isObject() { + return Object.class.equals(mClass); + } + + @Override + public boolean isVoid() { + return void.class.equals(mClass); + } + + @Override + public ClassClass unbox() { + if (mClass.isPrimitive()) { + return this; + } + if (Integer.class.equals(mClass)) { + return new ClassClass(int.class); + } else if (Long.class.equals(mClass)) { + return new ClassClass(long.class); + } else if (Short.class.equals(mClass)) { + return new ClassClass(short.class); + } else if (Byte.class.equals(mClass)) { + return new ClassClass(byte.class); + } else if (Character.class.equals(mClass)) { + return new ClassClass(char.class); + } else if (Double.class.equals(mClass)) { + return new ClassClass(double.class); + } else if (Float.class.equals(mClass)) { + return new ClassClass(float.class); + } else if (Boolean.class.equals(mClass)) { + return new ClassClass(boolean.class); + } else { + // not a boxed type + return this; + } + + } + + @Override + public ReflectionClass box() { + if (!mClass.isPrimitive()) { + return this; + } + if (int.class.equals(mClass)) { + return new ClassClass(Integer.class); + } else if (long.class.equals(mClass)) { + return new ClassClass(Long.class); + } else if (short.class.equals(mClass)) { + return new ClassClass(Short.class); + } else if (byte.class.equals(mClass)) { + return new ClassClass(Byte.class); + } else if (char.class.equals(mClass)) { + return new ClassClass(Character.class); + } else if (double.class.equals(mClass)) { + return new ClassClass(Double.class); + } else if (float.class.equals(mClass)) { + return new ClassClass(Float.class); + } else if (boolean.class.equals(mClass)) { + return new ClassClass(Boolean.class); + } else { + // not a valid type? + return this; + } + } + + @Override + public boolean isAssignableFrom(ReflectionClass that) { + Class thatClass = ((ClassClass) that).mClass; + return mClass.isAssignableFrom(thatClass); + } + + @Override + public ReflectionMethod[] getMethods(String name, int numParameters) { + Method[] methods = mClass.getMethods(); + ArrayList matching = new ArrayList<>(); + for (Method method : methods) { + if (method.getName().equals(name) && + method.getParameterTypes().length == numParameters) { + matching.add(new ClassMethod(method)); + } + } + return matching.toArray(new ReflectionMethod[matching.size()]); + } + + @Override + public ClassClass getSuperclass() { + return new ClassClass(mClass.getSuperclass()); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ClassClass) { + return mClass.equals(((ClassClass) obj).mClass); + } else { + return false; + } + } + + @Override + public int hashCode() { + return mClass.hashCode(); + } +} diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassField.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassField.java new file mode 100644 index 0000000000000..b5ea8f0a4a36b --- /dev/null +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassField.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 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 com.android.databinding.reflection; + +import java.lang.reflect.Field; + +public class ClassField implements ReflectionField { + + public final Field mField; + + public ClassField(Field field) { + mField = field; + } +} diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassMethod.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassMethod.java new file mode 100644 index 0000000000000..bbf6c3e6d0d6f --- /dev/null +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ClassMethod.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015 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 com.android.databinding.reflection; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class ClassMethod implements ReflectionMethod { + + public final Method mMethod; + + public ClassMethod(Method method) { + mMethod = method; + } + + + @Override + public ReflectionClass getDeclaringClass() { + return new ClassClass(mMethod.getDeclaringClass()); + } + + @Override + public ReflectionClass[] getParameterTypes() { + Class[] parameterTypes = mMethod.getParameterTypes(); + ReflectionClass[] parameterClasses = new ReflectionClass[parameterTypes.length]; + for (int i = 0; i < parameterTypes.length; i++) { + parameterClasses[i] = new ClassClass(parameterTypes[i]); + } + return parameterClasses; + } + + @Override + public String getName() { + return mMethod.getName(); + } + + @Override + public ReflectionClass getReturnType() { + return new ClassClass(mMethod.getReturnType()); + } + + @Override + public boolean isPublic() { + return Modifier.isPublic(mMethod.getModifiers()); + } + + @Override + public boolean isStatic() { + return Modifier.isStatic(mMethod.getModifiers()); + } +} diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionAnalyzer.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionAnalyzer.java new file mode 100644 index 0000000000000..4d5d49abc90fb --- /dev/null +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionAnalyzer.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 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 com.android.databinding.reflection; + +import java.net.URL; +import java.util.List; + +public abstract class ReflectionAnalyzer { + private static ReflectionAnalyzer sAnalyzer; + + public abstract boolean isDataBinder(ReflectionClass reflectionClass); + + public abstract Callable findMethod(ReflectionClass reflectionClass, String name, + List args); + + public abstract boolean isObservable(ReflectionClass reflectionClass); + + public abstract boolean isObservableField(ReflectionClass reflectionClass); + + public abstract boolean isBindable(ReflectionField field); + + public abstract boolean isBindable(ReflectionMethod method); + + public abstract Callable findMethodOrField(ReflectionClass klass, String name); + + public abstract ReflectionClass findCommonParentOf(ReflectionClass reflectionClass1, + ReflectionClass reflectionClass2); + + public abstract ReflectionClass loadPrimitive(String className); + + public static ReflectionAnalyzer getInstance() { + return sAnalyzer; + } + + public static void setClassLoader(ClassLoader classLoader) { + ClassAnalyzer.setClassLoader(classLoader); + sAnalyzer = ClassAnalyzer.getInstance(); + } + + public String getDefaultValue(String className) { + if("int".equals(className)) { + return "0"; + } + if("short".equals(className)) { + return "0"; + } + if("long".equals(className)) { + return "0L"; + } + if("float".equals(className)) { + return "0f"; + } + if("double".equals(className)) { + return "0.0"; + } + if("boolean".equals(className)) { + return "false"; + } + if ("char".equals(className)) { + return "'\\u0000'"; + } + if ("byte".equals(className)) { + return "0"; + } + return "null"; + } + + public abstract ReflectionClass findClass(String className); + + public abstract boolean isNullable(ReflectionClass reflectionClass); + + public abstract List getResources(String name); + + public abstract ReflectionClass findClass(Class classType); +} diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionClass.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionClass.java new file mode 100644 index 0000000000000..ef13ab2b86950 --- /dev/null +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionClass.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 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 com.android.databinding.reflection; + +import java.net.URL; +import java.util.List; + +public interface ReflectionClass { + + String toJavaCode(); + + boolean isArray(); + + ReflectionClass getComponentType(); + + boolean isList(); + + boolean isMap(); + + boolean isString(); + + boolean isNullable(); + + boolean isPrimitive(); + + boolean isBoolean(); + + boolean isChar(); + + boolean isByte(); + + boolean isShort(); + + boolean isInt(); + + boolean isLong(); + + boolean isFloat(); + + boolean isDouble(); + + boolean isObject(); + + boolean isVoid(); + + ReflectionClass unbox(); + + ReflectionClass box(); + + boolean isAssignableFrom(ReflectionClass that); + + ReflectionMethod[] getMethods(String name, int numParameters); + + ReflectionClass getSuperclass(); +} \ No newline at end of file diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionField.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionField.java new file mode 100644 index 0000000000000..78dfeca999ea2 --- /dev/null +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionField.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2015 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 com.android.databinding.reflection; + +public interface ReflectionField { + +} diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionMethod.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionMethod.java new file mode 100644 index 0000000000000..9f682ea2d54df --- /dev/null +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/reflection/ReflectionMethod.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 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 com.android.databinding.reflection; + +public interface ReflectionMethod { + ReflectionClass getDeclaringClass(); + + ReflectionClass[] getParameterTypes(); + + String getName(); + + ReflectionClass getReturnType(); + + boolean isPublic(); + + boolean isStatic(); +} diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/store/SetterStore.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/store/SetterStore.java index b85d73f96abed..58ac3b40be67c 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/store/SetterStore.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/store/SetterStore.java @@ -15,7 +15,9 @@ */ package com.android.databinding.store; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; +import com.android.databinding.reflection.ReflectionClass; +import com.android.databinding.reflection.ReflectionMethod; import java.io.File; import java.io.IOException; @@ -51,10 +53,10 @@ public class SetterStore { private static SetterStore sStore; private final IntermediateV1 mStore; - private final ClassAnalyzer mClassAnalyzer; + private final ReflectionAnalyzer mClassAnalyzer; - private SetterStore(ClassAnalyzer classAnalyzer, IntermediateV1 store) { - mClassAnalyzer = classAnalyzer; + private SetterStore(ReflectionAnalyzer reflectionAnalyzer, IntermediateV1 store) { + mClassAnalyzer = reflectionAnalyzer; mStore = store; } @@ -91,24 +93,22 @@ public class SetterStore { return sStore; } - public static SetterStore get(ClassAnalyzer classAnalyzer) { + public static SetterStore get(ReflectionAnalyzer reflectionAnalyzer) { if (sStore == null) { - sStore = load(classAnalyzer); + sStore = load(reflectionAnalyzer); } return sStore; } - private static SetterStore load(ClassAnalyzer classAnalyzer) { + private static SetterStore load(ReflectionAnalyzer reflectionAnalyzer) { IntermediateV1 store = new IntermediateV1(); String resourceName = SetterStore.class.getPackage().getName().replace('.', '/') + "/setter_store.bin"; try { - Enumeration resources = classAnalyzer.getClassLoader().getResources(resourceName); - while (resources.hasMoreElements()) { - URL resource = resources.nextElement(); + for (URL resource : reflectionAnalyzer.getResources(resourceName)) { merge(store, resource); } - return new SetterStore(classAnalyzer, store); + return new SetterStore(reflectionAnalyzer, store); } catch (IOException e) { System.err.println("Could not read SetterStore intermediate file: " + e.getLocalizedMessage()); @@ -118,7 +118,7 @@ public class SetterStore { e.getLocalizedMessage()); e.printStackTrace(); } - return new SetterStore(classAnalyzer, store); + return new SetterStore(reflectionAnalyzer, store); } private static SetterStore load(InputStream inputStream) @@ -282,8 +282,8 @@ public class SetterStore { } } - public String getSetterCall(String attribute, Class viewType, - Class valueType, String viewExpression, String valueExpression) { + public String getSetterCall(String attribute, ReflectionClass viewType, + ReflectionClass valueType, String viewExpression, String valueExpression) { if (!attribute.startsWith("android:")) { int colon = attribute.indexOf(':'); if (colon >= 0) { @@ -293,9 +293,9 @@ public class SetterStore { HashMap adapters = mStore.adapterMethods.get(attribute); MethodDescription adapter = null; String setterName = null; - Method bestSetterMethod = getBestSetter(viewType, valueType, attribute); - Class bestViewType = null; - Class bestValueType = null; + ReflectionMethod bestSetterMethod = getBestSetter(viewType, valueType, attribute); + ReflectionClass bestViewType = null; + ReflectionClass bestValueType = null; if (bestSetterMethod != null) { bestViewType = bestSetterMethod.getDeclaringClass(); bestValueType = bestSetterMethod.getParameterTypes()[0]; @@ -305,10 +305,10 @@ public class SetterStore { if (adapters != null) { for (AccessorKey key : adapters.keySet()) { try { - Class adapterViewType = mClassAnalyzer.findClass(key.viewType); + ReflectionClass adapterViewType = mClassAnalyzer.findClass(key.viewType); if (adapterViewType.isAssignableFrom(viewType)) { try { - Class adapterValueType = mClassAnalyzer.findClass(key.valueType); + ReflectionClass adapterValueType = mClassAnalyzer.findClass(key.valueType); boolean isBetterView = bestViewType == null || bestValueType.isAssignableFrom(adapterValueType); if (isBetterParameter(valueType, adapterValueType, bestValueType, @@ -327,8 +327,8 @@ public class SetterStore { } } - if (Object.class.equals(valueType) && !bestValueType.isAssignableFrom(valueType)) { - valueExpression = "(" + bestValueType.getCanonicalName() + ") " + valueExpression; + if (valueType.isObject() && !bestValueType.isAssignableFrom(valueType)) { + valueExpression = "(" + bestValueType.toJavaCode() + ") " + valueExpression; } MethodDescription conversionMethod = getConversionMethod(valueType, bestValueType); if (conversionMethod != null) { @@ -346,14 +346,15 @@ public class SetterStore { } } - private Method getBestSetter(Class viewType, Class argumentType, String attribute) { + private ReflectionMethod getBestSetter(ReflectionClass viewType, ReflectionClass argumentType, + String attribute) { String setterName = null; HashMap renamed = mStore.renamedMethods.get(attribute); if (renamed != null) { for (String className : renamed.keySet()) { try { - Class renamedViewType = mClassAnalyzer.findClass(className); + ReflectionClass renamedViewType = mClassAnalyzer.findClass(className); if (renamedViewType.isAssignableFrom(viewType)) { setterName = renamed.get(className).method; break; @@ -366,17 +367,14 @@ public class SetterStore { if (setterName == null) { setterName = getDefaultSetter(attribute); } - Method[] methods = viewType.getMethods(); + ReflectionMethod[] methods = viewType.getMethods(setterName, 1); - Class bestParameterType = null; - Method bestMethod = null; - for (Method method : methods) { - Class[] parameterTypes = method.getParameterTypes(); - if (parameterTypes.length == 1 && setterName.equals(method.getName()) && - void.class.equals(method.getReturnType()) && - !Modifier.isStatic(method.getModifiers()) && - Modifier.isPublic(method.getModifiers())) { - Class param = parameterTypes[0]; + ReflectionClass bestParameterType = null; + ReflectionMethod bestMethod = null; + for (ReflectionMethod method : methods) { + ReflectionClass[] parameterTypes = method.getParameterTypes(); + if (method.getReturnType().isVoid() && !method.isStatic() && method.isPublic()) { + ReflectionClass param = parameterTypes[0]; if (isBetterParameter(argumentType, param, bestParameterType, true)) { bestParameterType = param; bestMethod = method; @@ -394,8 +392,8 @@ public class SetterStore { return "set" + propertyName; } - private boolean isBetterParameter(Class argument, Class parameter, Class oldParameter, - boolean isBetterViewTypeMatch) { + private boolean isBetterParameter(ReflectionClass argument, ReflectionClass parameter, + ReflectionClass oldParameter, boolean isBetterViewTypeMatch) { // Right view type. Check the value if (!isBetterViewTypeMatch && oldParameter.equals(argument)) { return false; @@ -430,15 +428,14 @@ public class SetterStore { if (getConversionMethod(argument, oldParameter) != null) { return false; } - return argument.equals(Object.class) && !parameter.isPrimitive(); + return argument.isObject() && !parameter.isPrimitive(); } } } - private static boolean isImplicitConversion(Class from, Class to) { + private static boolean isImplicitConversion(ReflectionClass from, ReflectionClass to) { if (from != null && to != null && from.isPrimitive() && to.isPrimitive()) { - if (from.equals(boolean.class) || to.equals(boolean.class) || - to.equals(char.class)) { + if (from.isBoolean() || to.isBoolean() || to.isChar()) { return false; } int fromConversionLevel = getConversionLevel(from); @@ -449,17 +446,17 @@ public class SetterStore { } } - private MethodDescription getConversionMethod(Class from, Class to) { + private MethodDescription getConversionMethod(ReflectionClass from, ReflectionClass to) { if (from != null && to != null) { for (String fromClassName : mStore.conversionMethods.keySet()) { try { - Class convertFrom = mClassAnalyzer.findClass(fromClassName); + ReflectionClass convertFrom = mClassAnalyzer.findClass(fromClassName); if (canUseForConversion(from, convertFrom)) { HashMap conversion = mStore.conversionMethods.get(fromClassName); for (String toClassName : conversion.keySet()) { try { - Class convertTo = mClassAnalyzer.findClass(toClassName); + ReflectionClass convertTo = mClassAnalyzer.findClass(toClassName); if (canUseForConversion(convertTo, to)) { return conversion.get(toClassName); } @@ -476,90 +473,40 @@ public class SetterStore { return null; } - private static boolean canUseForConversion(Class from, Class to) { + private boolean canUseForConversion(ReflectionClass from, ReflectionClass to) { return from.equals(to) || isBoxingConversion(from, to) || to.isAssignableFrom(from); } - private static int getConversionLevel(Class primitive) { - if (byte.class.equals(primitive)) { + private static int getConversionLevel(ReflectionClass primitive) { + if (primitive == null) { + return -1; + } else if (primitive.isByte()) { return 0; - } else if (char.class.equals(primitive)) { + } else if (primitive.isChar()) { return 1; - } else if (short.class.equals(primitive)) { + } else if (primitive.isShort()) { return 2; - } else if (int.class.equals(primitive)) { + } else if (primitive.isInt()) { return 3; - } else if (long.class.equals(primitive)) { + } else if (primitive.isLong()) { return 4; - } else if (float.class.equals(primitive)) { + } else if (primitive.isFloat()) { return 5; - } else if (double.class.equals(primitive)) { + } else if (primitive.isDouble()) { return 6; } else { return -1; } } - public static boolean isBoxingConversion(Class class1, Class class2) { + public static boolean isBoxingConversion(ReflectionClass class1, ReflectionClass class2) { if (class1.isPrimitive() != class2.isPrimitive()) { - return (getWrappedType(class1).equals(getWrappedType(class2))); + return (class1.box().equals(class2.box())); } else { return false; } } - public static Class getWrappedType(Class type) { - if (!type.isPrimitive()) { - return type; - } - if (int.class.equals(type)) { - return Integer.class; - } else if (long.class.equals(type)) { - return Long.class; - } else if (short.class.equals(type)) { - return Short.class; - } else if (byte.class.equals(type)) { - return Byte.class; - } else if (char.class.equals(type)) { - return Character.class; - } else if (double.class.equals(type)) { - return Double.class; - } else if (float.class.equals(type)) { - return Float.class; - } else if (boolean.class.equals(type)) { - return Boolean.class; - } else { - // what type is this? - return type; - } - } - - public static Class getPrimitiveType(Class type) { - if (type.isPrimitive()) { - return type; - } - if (Integer.class.equals(type)) { - return int.class; - } else if (Long.class.equals(type)) { - return long.class; - } else if (Short.class.equals(type)) { - return short.class; - } else if (Byte.class.equals(type)) { - return byte.class; - } else if (Character.class.equals(type)) { - return char.class; - } else if (Double.class.equals(type)) { - return double.class; - } else if (Float.class.equals(type)) { - return float.class; - } else if (Boolean.class.equals(type)) { - return boolean.class; - } else { - // what type is this? - return type; - } - } - private static void merge(IntermediateV1 store, URL nextUrl) throws IOException, ClassNotFoundException { InputStream inputStream = null; diff --git a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/ext/ext.kt b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/ext/ext.kt index 946c7ccdb7d27..f870ca44930c0 100644 --- a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/ext/ext.kt +++ b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/ext/ext.kt @@ -17,7 +17,9 @@ import kotlin.properties.ReadOnlyProperty import kotlin.properties.Delegates import com.android.databinding.ext.joinToCamelCase import com.android.databinding.ext.joinToCamelCaseAsVar -import com.android.databinding.ClassAnalyzer +import com.android.databinding.reflection.ReflectionAnalyzer +import com.android.databinding.reflection.ReflectionClass +import com.android.databinding.reflection.ReflectionAnalyzer private class LazyExt(private val initializer: (k : K) -> T) : ReadOnlyProperty { private val mapping = hashMapOf() @@ -76,7 +78,3 @@ public fun String.toCamelCaseAsVar() : String { public fun String.br() : String = "android.binding.BR.${if (this == "") "_all" else this}" - -public fun Class<*>.getCodeName() : String = getName().replace("$", ".") - -public fun Class<*>.isObservable() : Boolean = ClassAnalyzer.getInstance().isObservable(this) diff --git a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/main.kt b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/main.kt index 4fdefe2eb23f2..0b5dd11f3e87f 100644 --- a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/main.kt +++ b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/main.kt @@ -50,7 +50,7 @@ import com.android.databinding.util.Log import com.android.databinding.LayoutBinder import com.android.databinding.DataBinder import com.android.databinding.writer.DataBinderWriter -import com.android.databinding.ClassAnalyzer +import com.android.databinding.reflection.ReflectionAnalyzer import com.android.databinding.util.ParserHelper import com.google.common.base.Preconditions @@ -59,7 +59,7 @@ public class KLayoutParser(val appPkg : String, val resourceFolders : kotlin.Ite val outputBaseDir : File, val outputResBaseDir : File) { var dbr : DataBinderWriter by Delegates.notNull() var processed = false - public var classAnalyzer : ClassAnalyzer by Delegates.notNull() + public var reflectionAnalyzer : ReflectionAnalyzer by Delegates.notNull() val jDataBinder = DataBinder(); diff --git a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt index 9d6a95cc6897d..1c2ec3c5fdab0 100644 --- a/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt +++ b/tools/data-binding/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt @@ -15,7 +15,7 @@ package com.android.databinding.writer import com.android.databinding.LayoutBinder import com.android.databinding.expr.Expr -import com.android.databinding.ClassAnalyzer +import com.android.databinding.reflection.ReflectionAnalyzer import kotlin.properties.Delegates import com.android.databinding.ext.joinToCamelCaseAsVar import com.android.databinding.BindingTarget @@ -42,9 +42,9 @@ import com.android.databinding.ext.androidId import com.android.databinding.ext.lazy import com.android.databinding.ext.br import com.android.databinding.ext.toJavaCode -import com.android.databinding.ext.isObservable import com.android.databinding.expr.ResourceExpr import com.android.databinding.expr.BracketExpr +import com.android.databinding.reflection.Callable fun String.stripNonJava() = this.split("[^a-zA-Z0-9]").map{ it.trim() }.joinToCamelCaseAsVar() @@ -160,7 +160,7 @@ fun Expr.toCode(full : Boolean = false) : KCode { } is FieldAccessExpr -> kcode("") { app("", it.getParent().toCode()) - if (it.getGetter().type == com.android.databinding.ClassAnalyzer.Callable.Type.FIELD) { + if (it.getGetter().type == Callable.Type.FIELD) { app(".", it.getGetter().name) } else { app(".", it.getGetter().name).app("()") @@ -602,8 +602,7 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder) { tab("// read ${expr.getUniqueKey()}") // create an if case for all dependencies that might be null val nullables = expr.getDependencies().filter { - it.isMandatory() && - ClassAnalyzer.isNullable(it.getOther().getResolvedType()) + it.isMandatory() && it.getOther().getResolvedType().isNullable() } .map { it.getOther() } if (!expr.isEqualityCheck() && nullables.isNotEmpty()) { diff --git a/tools/data-binding/compiler/src/test/java/com/android/databinding/ExpressionVisitorTest.java b/tools/data-binding/compiler/src/test/java/com/android/databinding/ExpressionVisitorTest.java index f4d0e237c192b..fa1e111aadb60 100644 --- a/tools/data-binding/compiler/src/test/java/com/android/databinding/ExpressionVisitorTest.java +++ b/tools/data-binding/compiler/src/test/java/com/android/databinding/ExpressionVisitorTest.java @@ -16,8 +16,6 @@ package com.android.databinding; -import com.android.databinding.ClassAnalyzer; -import com.android.databinding.ExpressionParser; import com.android.databinding.expr.ComparisonExpr; import com.android.databinding.expr.Dependency; import com.android.databinding.expr.Expr; @@ -27,6 +25,8 @@ import com.android.databinding.expr.IdentifierExpr; import com.android.databinding.expr.MethodCallExpr; import com.android.databinding.expr.SymbolExpr; import com.android.databinding.expr.TernaryExpr; +import com.android.databinding.reflection.Callable; +import com.android.databinding.reflection.ReflectionAnalyzer; import org.junit.Before; import org.junit.Test; @@ -43,7 +43,7 @@ public class ExpressionVisitorTest { @Before public void setUp() throws Exception { - ClassAnalyzer.initForTests(); + ReflectionAnalyzer.initForTests(); } private T parse(String input, Class klass) { @@ -69,7 +69,7 @@ public class ExpressionVisitorTest { @Before public void setUp() throws Exception { - ClassAnalyzer.initForTests(); + ReflectionAnalyzer.initForTests(); } @Parameterized.Parameters @@ -143,8 +143,8 @@ public class ExpressionVisitorTest { final IdentifierExpr id = (IdentifierExpr) parsed.getParent(); id.setUserDefinedType("java.lang.String"); assertSame(int.class, parsed.getResolvedType()); - ClassAnalyzer.Callable getter = parsed.getGetter(); - assertEquals(ClassAnalyzer.Callable.Type.METHOD, getter.type); + Callable getter = parsed.getGetter(); + assertEquals(Callable.Type.METHOD, getter.type); assertEquals("length", getter.name); assertEquals(1, parsed.getDependencies().size()); final Dependency dep = parsed.getDependencies().get(0); @@ -159,8 +159,8 @@ public class ExpressionVisitorTest { final IdentifierExpr id = (IdentifierExpr) parsed.getParent(); id.setUserDefinedType("java.lang.String"); assertSame(byte[].class, parsed.getResolvedType()); - ClassAnalyzer.Callable getter = parsed.getGetter(); - assertEquals(ClassAnalyzer.Callable.Type.METHOD, getter.type); + Callable getter = parsed.getGetter(); + assertEquals(Callable.Type.METHOD, getter.type); assertEquals("getBytes", getter.name); assertEquals(1, parsed.getDependencies().size()); final Dependency dep = parsed.getDependencies().get(0); diff --git a/tools/data-binding/compiler/src/test/java/com/android/databinding/LayoutBinderTest.java b/tools/data-binding/compiler/src/test/java/com/android/databinding/LayoutBinderTest.java index 0431d19a3a6ff..8859d3601c9e5 100644 --- a/tools/data-binding/compiler/src/test/java/com/android/databinding/LayoutBinderTest.java +++ b/tools/data-binding/compiler/src/test/java/com/android/databinding/LayoutBinderTest.java @@ -14,13 +14,13 @@ package com.android.databinding; -import com.android.databinding.ClassAnalyzer; -import com.android.databinding.LayoutBinder; import com.android.databinding.expr.Expr; import com.android.databinding.expr.ExprModel; import com.android.databinding.expr.FieldAccessExpr; import com.android.databinding.expr.IdentifierExpr; import com.android.databinding.expr.StaticIdentifierExpr; +import com.android.databinding.reflection.Callable; +import com.android.databinding.reflection.ReflectionAnalyzer; import org.junit.Before; import org.junit.Test; @@ -35,7 +35,7 @@ public class LayoutBinderTest { ExprModel mExprModel; @Before public void setUp() throws Exception { - ClassAnalyzer.initForTests(); + ReflectionAnalyzer.initForTests(); mLayoutBinder = new LayoutBinder(null); mExprModel = mLayoutBinder.getModel(); } @@ -91,8 +91,8 @@ public class LayoutBinderTest { IdentifierExpr id = mExprModel.identifier("user"); FieldAccessExpr fa = (FieldAccessExpr) item; fa.getResolvedType(); - final ClassAnalyzer.Callable getter = fa.getGetter(); - assertTrue(getter.type == ClassAnalyzer.Callable.Type.METHOD); + final Callable getter = fa.getGetter(); + assertTrue(getter.type == Callable.Type.METHOD); assertSame(id, fa.getParent()); assertTrue(fa.isDynamic()); } diff --git a/tools/data-binding/compiler/src/test/java/com/android/databinding/expr/ExprModelTest.java b/tools/data-binding/compiler/src/test/java/com/android/databinding/expr/ExprModelTest.java index 96d1a2f1f165c..f2b2236ffbfdd 100644 --- a/tools/data-binding/compiler/src/test/java/com/android/databinding/expr/ExprModelTest.java +++ b/tools/data-binding/compiler/src/test/java/com/android/databinding/expr/ExprModelTest.java @@ -19,7 +19,7 @@ package com.android.databinding.expr; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; import com.android.databinding.LayoutBinder; import com.android.databinding.util.L; @@ -45,7 +45,7 @@ public class ExprModelTest { } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { + protected Class resolveType(ReflectionAnalyzer reflectionAnalyzer) { return Integer.class; } @@ -77,7 +77,7 @@ public class ExprModelTest { @Before public void setUp() throws Exception { - ClassAnalyzer.initForTests(); + ReflectionAnalyzer.initForTests(); mExprModel = new ExprModel(); } diff --git a/tools/data-binding/compiler/src/test/java/com/android/databinding/expr/ExprTest.java b/tools/data-binding/compiler/src/test/java/com/android/databinding/expr/ExprTest.java index dd21d25480f43..fd6daf87d52d6 100644 --- a/tools/data-binding/compiler/src/test/java/com/android/databinding/expr/ExprTest.java +++ b/tools/data-binding/compiler/src/test/java/com/android/databinding/expr/ExprTest.java @@ -16,7 +16,7 @@ package com.android.databinding.expr; -import com.android.databinding.ClassAnalyzer; +import com.android.databinding.reflection.ReflectionAnalyzer; import org.junit.Before; import org.junit.Test; @@ -37,7 +37,7 @@ public class ExprTest{ } @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { + protected Class resolveType(ReflectionAnalyzer reflectionAnalyzer) { return Integer.class; } @@ -59,14 +59,14 @@ public class ExprTest{ @Before public void setUp() throws Exception { - ClassAnalyzer.initForTests(); + ReflectionAnalyzer.initForTests(); } @Test(expected=IllegalStateException.class) public void testBadExpr() { Expr expr = new Expr() { @Override - protected Class resolveType(ClassAnalyzer classAnalyzer) { + protected Class resolveType(ReflectionAnalyzer reflectionAnalyzer) { return Integer.class; } diff --git a/tools/data-binding/gradlePlugin/src/main/kotlin/plugin.kt b/tools/data-binding/gradlePlugin/src/main/kotlin/plugin.kt index 3725616d99faa..4b66e77101199 100644 --- a/tools/data-binding/gradlePlugin/src/main/kotlin/plugin.kt +++ b/tools/data-binding/gradlePlugin/src/main/kotlin/plugin.kt @@ -44,6 +44,7 @@ import javax.tools.JavaCompiler import javax.tools.ToolProvider import java.util.Arrays import org.apache.commons.io.FileUtils +import com.android.databinding.reflection.ReflectionAnalyzer class DataBinderPlugin : Plugin { var parser: KLayoutParser by Delegates.notNull() @@ -177,8 +178,8 @@ class DataBinderPlugin : Plugin { log("generated urls: ${urls} len: ${urls.size}") val classLoader = URLClassLoader(urls, androidClassLoader) log("created class loader") - ClassAnalyzer.setClassLoader(classLoader) - parser.classAnalyzer = ClassAnalyzer.getInstance() + ReflectionAnalyzer.setClassLoader(classLoader) + parser.reflectionAnalyzer = ReflectionAnalyzer.getInstance() project.task("compileGenerated", MethodClosure(this, "compileGenerated")) }