diff options
author | George Mount <mount@google.com> | 2016-04-21 13:27:52 -0700 |
---|---|---|
committer | George Mount <mount@google.com> | 2016-05-05 10:00:13 -0700 |
commit | 78dc9ae6d67ae94bf3f637eeea0848e4f700b7a3 (patch) | |
tree | 80f71b808b614afe658fd2e2efbc532f82b8c102 | |
parent | c4befae8ade4e14e10a39c259228f142d624a801 (diff) | |
download | data-binding-78dc9ae6d67ae94bf3f637eeea0848e4f700b7a3.tar.gz |
Fix problem where root View's style is used instead of bound View's
Bug 27808662
Change-Id: I870b0db47e3ed970a3bd67e602e873e503610028
13 files changed, 97 insertions, 44 deletions
diff --git a/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java b/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java index a4c7af9c..ee5467e2 100644 --- a/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java +++ b/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java @@ -396,7 +396,7 @@ public class SimpleCompilationTest extends BaseCompilationTest { } ModelMethod modelMethod = injectedClass.getMethod( method.getName(), args, Modifier.isStatic(method.getModifiers()), false); - assertNotNull(modelMethod); + assertNotNull("Method " + method + " not found", modelMethod); } } } diff --git a/compiler/src/main/java/android/databinding/tool/CompilerChef.java b/compiler/src/main/java/android/databinding/tool/CompilerChef.java index 611f3b8f..c167207a 100644 --- a/compiler/src/main/java/android/databinding/tool/CompilerChef.java +++ b/compiler/src/main/java/android/databinding/tool/CompilerChef.java @@ -135,6 +135,11 @@ public class CompilerChef { "java.lang.Object"); injectedClass.addMethod(new InjectedMethod(injectedClass, true, "getColorFromResource", "int", "android.view.View", "int")); + injectedClass.addMethod(new InjectedMethod(injectedClass, true, + "getColorStateListFromResource", "android.content.res.ColorStateList", + "android.view.View", "int")); + injectedClass.addMethod(new InjectedMethod(injectedClass, true, "getDrawableFromResource", + "android.graphics.drawable.Drawable", "android.view.View", "int")); injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse", "boolean", "java.lang.String", "boolean")); injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse", diff --git a/compiler/src/main/java/android/databinding/tool/ExpressionParser.java b/compiler/src/main/java/android/databinding/tool/ExpressionParser.java index 8deebc4d..18fb8399 100644 --- a/compiler/src/main/java/android/databinding/tool/ExpressionParser.java +++ b/compiler/src/main/java/android/databinding/tool/ExpressionParser.java @@ -50,11 +50,12 @@ public class ExpressionParser { visitor = new ExpressionVisitor(mModel); } - public Expr parse(String input, @Nullable Location locationInFile) { + public Expr parse(String input, @Nullable Location locationInFile, BindingTarget target) { ANTLRInputStream inputStream = new ANTLRInputStream(input); BindingExpressionLexer lexer = new BindingExpressionLexer(inputStream); CommonTokenStream tokenStream = new CommonTokenStream(lexer); final BindingExpressionParser parser = new BindingExpressionParser(tokenStream); + visitor.setBindingTarget(target); parser.addErrorListener(new BaseErrorListener() { @Override public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, diff --git a/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java b/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java index 87426c0f..d273f387 100644 --- a/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java +++ b/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java @@ -47,6 +47,7 @@ class ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> { private ExprModel mModel; private ParseTreeListener mParseTreeListener; private ArrayDeque<ExprModel> mModelStack = new ArrayDeque<ExprModel>(); + private BindingTarget mTarget; ExpressionVisitor(ExprModel model) { mModel = model; @@ -56,6 +57,10 @@ class ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> { mParseTreeListener = parseTreeListener; } + public void setBindingTarget(BindingTarget bindingTarget) { + mTarget = bindingTarget; + } + private void onEnter(ParserRuleContext context) { if (mParseTreeListener != null) { mParseTreeListener.enterEveryRule(context); @@ -398,7 +403,7 @@ class ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> { final int startIndex = Math.max(1, colonIndex + 1); final String resourceType = resourceReference.substring(startIndex, slashIndex).trim(); final String resourceName = resourceReference.substring(slashIndex + 1).trim(); - return mModel.resourceExpr(packageName, resourceType, resourceName, args); + return mModel.resourceExpr(mTarget, packageName, resourceType, resourceName, args); } finally { onExit(ctx); } diff --git a/compiler/src/main/java/android/databinding/tool/LayoutBinder.java b/compiler/src/main/java/android/databinding/tool/LayoutBinder.java index c7704682..bcbafda6 100644 --- a/compiler/src/main/java/android/databinding/tool/LayoutBinder.java +++ b/compiler/src/main/java/android/databinding/tool/LayoutBinder.java @@ -222,7 +222,8 @@ public class LayoutBinder implements FileScopeProvider { try { Scope.enter(bindingBundle.getValueLocation()); Expr expr = parse(bindingBundle.getExpr(), - bindingBundle.getValueLocation()); + bindingBundle.getValueLocation(), + bindingTarget); bindingTarget.addBinding(bindingBundle.getName(), expr); if (bindingBundle.isTwoWay()) { bindingTarget.addInverseBinding(bindingBundle.getName(), expr, @@ -295,8 +296,8 @@ public class LayoutBinder implements FileScopeProvider { return target; } - public Expr parse(String input, @Nullable Location locationInFile) { - final Expr parsed = mExpressionParser.parse(input, locationInFile); + public Expr parse(String input, @Nullable Location locationInFile, BindingTarget target) { + final Expr parsed = mExpressionParser.parse(input, locationInFile, target); parsed.setBindingExpression(true); return parsed; } diff --git a/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java b/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java index 87169cee..34b25690 100644 --- a/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java +++ b/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java @@ -273,9 +273,9 @@ public class ExprModel { return register(new UnaryExpr(op, expr)); } - public Expr resourceExpr(String packageName, String resourceType, String resourceName, - List<Expr> args) { - return register(new ResourceExpr(packageName, resourceType, resourceName, args)); + public Expr resourceExpr(BindingTarget target, String packageName, String resourceType, + String resourceName, List<Expr> args) { + return register(new ResourceExpr(target, packageName, resourceType, resourceName, args)); } public Expr bracketExpr(Expr variableExpr, Expr argExpr) { diff --git a/compiler/src/main/java/android/databinding/tool/expr/ResourceExpr.java b/compiler/src/main/java/android/databinding/tool/expr/ResourceExpr.java index 2ecf5fb0..df36cf63 100644 --- a/compiler/src/main/java/android/databinding/tool/expr/ResourceExpr.java +++ b/compiler/src/main/java/android/databinding/tool/expr/ResourceExpr.java @@ -15,9 +15,11 @@ */ package android.databinding.tool.expr; +import android.databinding.tool.BindingTarget; import android.databinding.tool.reflection.ModelAnalyzer; import android.databinding.tool.reflection.ModelClass; import android.databinding.tool.writer.KCode; +import android.databinding.tool.writer.LayoutBinderWriterKt; import java.util.HashMap; import java.util.List; @@ -45,9 +47,12 @@ public class ResourceExpr extends Expr { protected final String mResourceId; - public ResourceExpr(String packageName, String resourceType, String resourceName, - List<Expr> args) { + protected final BindingTarget mTarget; + + public ResourceExpr(BindingTarget target, String packageName, String resourceType, + String resourceName, List<Expr> args) { super(args); + mTarget = target; if ("android".equals(packageName)) { mPackage = "android."; } else { @@ -121,7 +126,11 @@ public class ResourceExpr extends Expr { @Override protected String computeUniqueKey() { String base = toString(); - return join(base, computeChildrenKey()); + String view = ""; + if (requiresView()) { + view = LayoutBinderWriterKt.getFieldName(mTarget); + } + return join(base, view, computeChildrenKey()); } @Override @@ -132,7 +141,7 @@ public class ResourceExpr extends Expr { @Override public Expr cloneToModel(ExprModel model) { String pkg = mPackage.isEmpty() ? "" : "android"; - return model.resourceExpr(pkg, mResourceType, mResourceId, + return model.resourceExpr(mTarget, pkg, mResourceType, mResourceId, cloneToModel(model, getChildren())); } @@ -146,19 +155,31 @@ public class ResourceExpr extends Expr { computeUniqueKey(); } + private boolean requiresView() { + return !mTarget.isBinder() && !("anim".equals(mResourceType) || + "animator".equals(mResourceType) || + "id".equals(mResourceType) || + "interpolator".equals(mResourceType) || + "layout".equals(mResourceType) || + "stateListAnimator".equals(mResourceType) || + "transition".equals(mResourceType)); + } + public String toJava() { final String context = "getRoot().getContext()"; - final String resources = "getRoot().getResources()"; + final String viewName = requiresView() ? LayoutBinderWriterKt.getFieldName(mTarget) : + "getRoot()"; + final String resources = viewName + ".getResources()"; final String resourceName = mPackage + "R." + getResourceObject() + "." + mResourceId; if ("anim".equals(mResourceType)) return "android.view.animation.AnimationUtils.loadAnimation(" + context + ", " + resourceName + ")"; if ("animator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadAnimator(" + context + ", " + resourceName + ")"; if ("bool".equals(mResourceType)) return resources + ".getBoolean(" + resourceName + ")"; - if ("color".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorFromResource(getRoot(), " + resourceName + ")"; - if ("colorStateList".equals(mResourceType)) return "getColorStateListFromResource(" + resourceName + ")"; + if ("color".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorFromResource(" + viewName + ", " + resourceName + ")"; + if ("colorStateList".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorStateListFromResource(" + viewName + ", " + resourceName + ")"; if ("dimen".equals(mResourceType)) return resources + ".getDimension(" + resourceName + ")"; if ("dimenOffset".equals(mResourceType)) return resources + ".getDimensionPixelOffset(" + resourceName + ")"; if ("dimenSize".equals(mResourceType)) return resources + ".getDimensionPixelSize(" + resourceName + ")"; - if ("drawable".equals(mResourceType)) return "getDrawableFromResource(" + resourceName + ")"; + if ("drawable".equals(mResourceType)) return "android.databinding.DynamicUtil.getDrawableFromResource(" + viewName + ", " + resourceName + ")"; if ("fraction".equals(mResourceType)) { String base = getChildCode(0, "1"); String pbase = getChildCode(1, "1"); @@ -174,11 +195,11 @@ public class ResourceExpr extends Expr { if (getChildren().isEmpty()) { return resourceName; } else { - return makeParameterCall(resourceName, "getQuantityString"); + return makeParameterCall(resources, resourceName, "getQuantityString"); } } if ("stateListAnimator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadStateListAnimator(" + context + ", " + resourceName + ")"; - if ("string".equals(mResourceType)) return makeParameterCall(resourceName, "getString"); + if ("string".equals(mResourceType)) return makeParameterCall(resources, resourceName, "getString"); if ("stringArray".equals(mResourceType)) return resources + ".getStringArray(" + resourceName + ")"; if ("transition".equals(mResourceType)) return "android.transition.TransitionInflater.from(" + context + ").inflateTransition(" + resourceName + ")"; if ("typedArray".equals(mResourceType)) return resources + ".obtainTypedArray(" + resourceName + ")"; @@ -196,9 +217,9 @@ public class ResourceExpr extends Expr { } } - private String makeParameterCall(String resourceName, String methodCall) { - StringBuilder sb = new StringBuilder("getRoot().getResources()."); - sb.append(methodCall).append("(").append(resourceName); + private String makeParameterCall(String resources, String resourceName, String methodCall) { + StringBuilder sb = new StringBuilder(resources); + sb.append('.').append(methodCall).append("(").append(resourceName); for (Expr expr : getChildren()) { sb.append(", ").append(expr.toCode().generate()); } diff --git a/compiler/src/main/kotlin/android/databinding/tool/writer/DynamicUtilWriter.kt b/compiler/src/main/kotlin/android/databinding/tool/writer/DynamicUtilWriter.kt index 8d76b030..e7314606 100644 --- a/compiler/src/main/kotlin/android/databinding/tool/writer/DynamicUtilWriter.kt +++ b/compiler/src/main/kotlin/android/databinding/tool/writer/DynamicUtilWriter.kt @@ -8,13 +8,33 @@ class DynamicUtilWriter() { nl("") block("public class DynamicUtil") { nl("@SuppressWarnings(\"deprecation\")") - block("public static int getColorFromResource(final android.view.View root, final int resourceId)") { + block("public static int getColorFromResource(final android.view.View view, final int resourceId)") { if (targetSdk >= 23) { block("if (VERSION.SDK_INT >= VERSION_CODES.M)") { - nl("return root.getContext().getColor(resourceId);") + nl("return view.getContext().getColor(resourceId);") } } - nl("return root.getResources().getColor(resourceId);") + nl("return view.getResources().getColor(resourceId);") + } + + nl("@SuppressWarnings(\"deprecation\")") + block("public static android.content.res.ColorStateList getColorStateListFromResource(final android.view.View view, final int resourceId)") { + if (targetSdk >= 23) { + block("if (VERSION.SDK_INT >= VERSION_CODES.M)") { + nl("return view.getContext().getColorStateList(resourceId);") + } + } + nl("return view.getResources().getColorStateList(resourceId);") + } + + nl("@SuppressWarnings(\"deprecation\")") + block("public static android.graphics.drawable.Drawable getDrawableFromResource(final android.view.View view, final int resourceId)") { + if (targetSdk >= 21) { + block("if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)") { + nl("return view.getContext().getDrawable(resourceId);") + } + } + nl("return view.getResources().getDrawable(resourceId);") } block("public static boolean parse(String str, boolean fallback)") { diff --git a/compiler/src/test/java/android/databinding/tool/ExpressionVisitorTest.java b/compiler/src/test/java/android/databinding/tool/ExpressionVisitorTest.java index 84b032af..3d3d8fed 100644 --- a/compiler/src/test/java/android/databinding/tool/ExpressionVisitorTest.java +++ b/compiler/src/test/java/android/databinding/tool/ExpressionVisitorTest.java @@ -51,7 +51,7 @@ public class ExpressionVisitorTest { } private <T extends Expr> T parse(String input, Class<T> klass) { - final Expr parsed = mParser.parse(input, null); + final Expr parsed = mParser.parse(input, null, null); assertSame(klass, parsed.getClass()); return (T) parsed; } @@ -89,7 +89,7 @@ public class ExpressionVisitorTest { @Test public void testComparison() { - final Expr res = mParser.parse("3 " + mOp + " 5", null); + final Expr res = mParser.parse("3 " + mOp + " 5", null, null); assertEquals(3, mParser.getModel().size()); assertTrue(res instanceof ComparisonExpr); // 0 because they are both static @@ -180,7 +180,7 @@ public class ExpressionVisitorTest { assertEquals(0, parsed.getArgs().size()); assertEquals(1, parsed.getDependencies().size()); final Dependency dep = parsed.getDependencies().get(0); - assertSame(mParser.parse("user", null), dep.getOther()); + assertSame(mParser.parse("user", null, null), dep.getOther()); assertFalse(dep.isConditional()); } diff --git a/compiler/src/test/java/android/databinding/tool/LayoutBinderTest.java b/compiler/src/test/java/android/databinding/tool/LayoutBinderTest.java index c7f81ab1..564ecef4 100644 --- a/compiler/src/test/java/android/databinding/tool/LayoutBinderTest.java +++ b/compiler/src/test/java/android/databinding/tool/LayoutBinderTest.java @@ -77,8 +77,8 @@ public class LayoutBinderTest { int originalSize = mExprModel.size(); mLayoutBinder.addVariable("user", "android.databinding.tool2.LayoutBinderTest.TestUser", null); - mLayoutBinder.parse("user.name", null); - mLayoutBinder.parse("user.lastName", null); + mLayoutBinder.parse("user.name", null, null); + mLayoutBinder.parse("user.lastName", null, null); assertEquals(originalSize + 3, mExprModel.size()); final List<Expr> bindingExprs = mExprModel.getBindingExpressions(); assertEquals(2, bindingExprs.size()); @@ -94,7 +94,7 @@ public class LayoutBinderTest { public void testParseWithMethods() { mLayoutBinder.addVariable("user", "android.databinding.tool.LayoutBinderTest.TestUser", null); - mLayoutBinder.parse("user.fullName", null); + mLayoutBinder.parse("user.fullName", null, null); Expr item = mExprModel.getBindingExpressions().get(0); assertTrue(item instanceof FieldAccessExpr); IdentifierExpr id = mExprModel.identifier("user"); diff --git a/compiler/src/test/java/android/databinding/tool/expr/ExecutionPathTest.java b/compiler/src/test/java/android/databinding/tool/expr/ExecutionPathTest.java index 2bb8832f..d6fb4707 100644 --- a/compiler/src/test/java/android/databinding/tool/expr/ExecutionPathTest.java +++ b/compiler/src/test/java/android/databinding/tool/expr/ExecutionPathTest.java @@ -57,7 +57,7 @@ public class ExecutionPathTest { public void simpleExpr() { MockLayoutBinder lb = new MockLayoutBinder(); ExprModel model = lb.getModel(); - Expr parsed = lb.parse(mExpression, null); + Expr parsed = lb.parse(mExpression, null, null); List<ExecutionPath> paths = new ArrayList<ExecutionPath>(); ExecutionPath root = ExecutionPath.createRoot(); paths.add(root); diff --git a/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java b/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java index e20dea74..a661c30f 100644 --- a/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java +++ b/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java @@ -154,7 +154,7 @@ public class ExprModelTest { IdentifierExpr a = lb.addVariable("a", "java.lang.String", null); IdentifierExpr b = lb.addVariable("b", "java.lang.String", null); IdentifierExpr c = lb.addVariable("c", "java.lang.String", null); - lb.parse("a == null ? b : c", null); + lb.parse("a == null ? b : c", null, null); mExprModel.comparison("==", a, mExprModel.symbol("null", Object.class)); lb.getModel().seal(); List<Expr> shouldRead = getShouldRead(); @@ -303,7 +303,7 @@ public class ExprModelTest { IdentifierExpr c = lb.addVariable("c", "java.lang.String", null); IdentifierExpr d = lb.addVariable("d", "java.lang.String", null); IdentifierExpr e = lb.addVariable("e", "java.lang.String", null); - final Expr aTernary = lb.parse("a == null ? b == null ? c : d : e", null); + final Expr aTernary = lb.parse("a == null ? b == null ? c : d : e", null, null); assertTrue(aTernary instanceof TernaryExpr); final Expr bTernary = ((TernaryExpr) aTernary).getIfTrue(); assertTrue(bTernary instanceof TernaryExpr); @@ -1132,7 +1132,7 @@ public class ExprModelTest { } private <T extends Expr> T parse(LayoutBinder binder, String input, Class<T> klass) { - final Expr parsed = binder.parse(input, null); + final Expr parsed = binder.parse(input, null, null); assertTrue(klass.isAssignableFrom(parsed.getClass())); return (T) parsed; } diff --git a/extensions/library/src/main/java/android/databinding/ViewDataBinding.java b/extensions/library/src/main/java/android/databinding/ViewDataBinding.java index 7829c0d1..f50267b8 100644 --- a/extensions/library/src/main/java/android/databinding/ViewDataBinding.java +++ b/extensions/library/src/main/java/android/databinding/ViewDataBinding.java @@ -640,29 +640,29 @@ public abstract class ViewDataBinding extends BaseObservable { } /** @hide */ - protected int getColorFromResource(int resourceId) { + protected static int getColorFromResource(View view, int resourceId) { if (VERSION.SDK_INT >= VERSION_CODES.M) { - return getRoot().getContext().getColor(resourceId); + return view.getContext().getColor(resourceId); } else { - return getRoot().getResources().getColor(resourceId); + return view.getResources().getColor(resourceId); } } /** @hide */ - protected ColorStateList getColorStateListFromResource(int resourceId) { + protected static ColorStateList getColorStateListFromResource(View view, int resourceId) { if (VERSION.SDK_INT >= VERSION_CODES.M) { - return getRoot().getContext().getColorStateList(resourceId); + return view.getContext().getColorStateList(resourceId); } else { - return getRoot().getResources().getColorStateList(resourceId); + return view.getResources().getColorStateList(resourceId); } } /** @hide */ - protected Drawable getDrawableFromResource(int resourceId) { + protected static Drawable getDrawableFromResource(View view, int resourceId) { if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { - return getRoot().getContext().getDrawable(resourceId); + return view.getContext().getDrawable(resourceId); } else { - return getRoot().getResources().getDrawable(resourceId); + return view.getResources().getDrawable(resourceId); } } |