diff options
author | Yigit Boyar <yboyar@google.com> | 2015-03-27 14:10:13 -0700 |
---|---|---|
committer | Yigit Boyar <yboyar@google.com> | 2015-04-03 10:00:25 -0700 |
commit | 3695b1aae95b289302cbbf9c38f0bd595bfc6ccb (patch) | |
tree | 5610ea4d6614ad592737ecd7d9de4ca9fa93bec3 | |
parent | 53a6b1bde897f8a837cdf628201d8341aecb3a61 (diff) | |
download | frameworks_base-3695b1aae95b289302cbbf9c38f0bd595bfc6ccb.zip frameworks_base-3695b1aae95b289302cbbf9c38f0bd595bfc6ccb.tar.gz frameworks_base-3695b1aae95b289302cbbf9c38f0bd595bfc6ccb.tar.bz2 |
Fix bugs related to how we handle Ternary ops
This CL fixes two bugs.
1) When a Ternary operation was inside another operation, we were
not handling dependecies properly and model would think that
the container expression can be evaluated before Ternary is evaluated,
eventually causing an exception in code-gen because Ternay is not
calculated yet.
2) This also fixes another bug where when ?? is used, we would put
ifTrue and ifFalse statements in wrong order and eventually evaluate
!??.
Bug: 19939148
Change-Id: I3e1d2bee172e47412bb8ef9e7c785aef47337155
10 files changed, 224 insertions, 58 deletions
diff --git a/tools/data-binding/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java b/tools/data-binding/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java index 879c439..a30f59b 100644 --- a/tools/data-binding/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java +++ b/tools/data-binding/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java @@ -93,7 +93,7 @@ public class ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> { 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)), - left, ctx.right.accept(this)); + ctx.right.accept(this), left); } @Override diff --git a/tools/data-binding/compiler/src/main/java/android/databinding/tool/expr/Expr.java b/tools/data-binding/compiler/src/main/java/android/databinding/tool/expr/Expr.java index a7cd412..09b96d8 100644 --- a/tools/data-binding/compiler/src/main/java/android/databinding/tool/expr/Expr.java +++ b/tools/data-binding/compiler/src/main/java/android/databinding/tool/expr/Expr.java @@ -400,17 +400,12 @@ abstract public class Expr { return mRead; } - public boolean considerElevatingConditionals(Expr cond) { + public boolean considerElevatingConditionals(Expr justRead) { boolean elevated = false; for (Dependency dependency : mDependencies) { - if (dependency.isConditional() && dependency.getCondition() == cond) { + if (dependency.isConditional() && dependency.getCondition() == justRead) { dependency.elevate(); - // silent elevate because it is not necessary anymore (already calculated) - // but need to mark dependencies elevated so that we can decide to calculate - // this expression when all dependencies are elevated - if (!dependency.getOther().isRead()) { - elevated = true; - } + elevated = true; } } return elevated; @@ -433,7 +428,7 @@ abstract public class Expr { Predicate<Dependency> hasNestedCannotRead = new Predicate<Dependency>() { @Override public boolean apply(Dependency input) { - return input.getOther().hasNestedCannotRead(); + return input.isConditional() || input.getOther().hasNestedCannotRead(); } }; @@ -470,6 +465,9 @@ abstract public class Expr { } } + if (mRead) { + mShouldReadFlags = null; // if we've been marked as read, clear should read flags + } return mRead; } diff --git a/tools/data-binding/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java b/tools/data-binding/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java index e3ec30a..0f8a935 100644 --- a/tools/data-binding/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java +++ b/tools/data-binding/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java @@ -26,6 +26,7 @@ import android.databinding.tool.util.L; import android.databinding.tool.writer.FlagSet; import java.util.ArrayList; +import java.util.Arrays; import java.util.BitSet; import java.util.HashMap; import java.util.List; @@ -437,12 +438,12 @@ public class ExprModel { return elevated; } - public Iterable<Expr> filterShouldRead(Iterable<Expr> exprs) { - return Iterables.filter(exprs, sShouldReadPred); + public static Iterable<Expr> filterShouldRead(Iterable<Expr> exprs) { + return toCollection(Iterables.filter(exprs, sShouldReadPred)); } - public Iterable<Expr> filterCanBeReadNow(Iterable<Expr> exprs) { - return Iterables.filter(exprs, sReadNowPred); + public static List<Expr> toCollection(Iterable<Expr> iterable) { + return Arrays.asList(Iterables.toArray(iterable, Expr.class)); } private static final Predicate<Expr> sShouldReadPred = new Predicate<Expr>() { diff --git a/tools/data-binding/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt b/tools/data-binding/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt index 228e759..763c94b 100644 --- a/tools/data-binding/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt +++ b/tools/data-binding/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt @@ -679,7 +679,7 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder) { } do { - val batch = model.filterShouldRead(model.getPendingExpressions()).toArrayList() + val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList() val mJustRead = arrayListOf<Expr>() while (!batch.none()) { val readNow = batch.filter { it.shouldReadNow(mJustRead) } @@ -758,8 +758,7 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder) { // create an if case for all dependencies that might be null val nullables = expr.getDependencies().filter { it.isMandatory() && it.getOther().getResolvedType().isNullable() - } - .map { it.getOther() } + }.map { it.getOther() } if (!expr.isEqualityCheck() && nullables.isNotEmpty()) { tab ("if ( ${nullables.map { "${it.localName} != null" }.joinToString(" && ")}) {") { tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";") diff --git a/tools/data-binding/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java b/tools/data-binding/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java index ed9934d..7bccd6e 100644 --- a/tools/data-binding/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java +++ b/tools/data-binding/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java @@ -34,6 +34,8 @@ import android.databinding.tool.reflection.ModelClass; import android.databinding.tool.reflection.java.JavaAnalyzer; import android.databinding.tool.util.L; +import java.util.ArrayList; +import java.util.Arrays; import java.util.BitSet; import java.util.List; @@ -45,8 +47,11 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; public class ExprModelTest { + private static class DummyExpr extends Expr { + String mKey; + public DummyExpr(String key, DummyExpr... children) { super(children); mKey = key; @@ -76,7 +81,7 @@ public class ExprModelTest { protected void failed(Throwable e, Description description) { if (mExprModel != null && mExprModel.getFlagMapping() != null) { final String[] mapping = mExprModel.getFlagMapping(); - for (int i = 0; i < mapping.length; i ++) { + for (int i = 0; i < mapping.length; i++) { L.d("flag %d: %s", i, mapping[i]); } } @@ -96,6 +101,7 @@ public class ExprModelTest { assertSame(d, mExprModel.register(d)); assertEquals(1, mExprModel.mExprMap.size()); } + @Test public void testAddDupe1() { final DummyExpr d = new DummyExpr("a"); @@ -131,8 +137,8 @@ public class ExprModelTest { IdentifierExpr a = lb.addVariable("a", "java.lang.String"); IdentifierExpr b = lb.addVariable("b", "java.lang.String"); IdentifierExpr c = lb.addVariable("c", "java.lang.String"); - final Expr ternary = lb.parse("a == null ? b : c"); - final Expr equality = mExprModel.comparison("==", a, mExprModel.symbol("null", Object.class)); + lb.parse("a == null ? b : c"); + mExprModel.comparison("==", a, mExprModel.symbol("null", Object.class)); lb.getModel().seal(); Iterable<Expr> shouldRead = getShouldRead(); // a and a == null @@ -147,6 +153,59 @@ public class ExprModelTest { } @Test + public void testTernaryWithPlus() { + LayoutBinder lb = new MockLayoutBinder(); + mExprModel = lb.getModel(); + IdentifierExpr user = lb + .addVariable("user", "android.databinding.tool.expr.ExprModelTest.User"); + MathExpr parsed = parse(lb, "user.name + \" \" + (user.lastName ?? \"\")", MathExpr.class); + mExprModel.seal(); + Iterable<Expr> toRead = getShouldRead(); + Iterable<Expr> readNow = getReadFirst(toRead); + assertEquals(1, Iterables.size(readNow)); + assertSame(user, Iterables.getFirst(readNow, null)); + List<Expr> justRead = new ArrayList<Expr>(); + justRead.add(user); + readNow = filterOut(getReadFirst(toRead, justRead), justRead); + assertEquals(2, Iterables.size(readNow)); //user.name && user.lastName + Iterables.addAll(justRead, readNow); + // user.lastname (T, F), user.name + " " + readNow = filterOut(getReadFirst(toRead, justRead), justRead); + assertEquals(2, Iterables.size(readNow)); //user.name && user.lastName + Iterables.addAll(justRead, readNow); + readNow = filterOut(getReadFirst(toRead, justRead), justRead); + assertEquals(0, Iterables.size(readNow)); + mExprModel.markBitsRead(); + + toRead = getShouldRead(); + assertEquals(2, Iterables.size(toRead)); + justRead.clear(); + readNow = filterOut(getReadFirst(toRead, justRead), justRead); + assertEquals(1, Iterables.size(readNow)); + assertSame(parsed.getRight(), Iterables.getFirst(readNow, null)); + Iterables.addAll(justRead, readNow); + + readNow = filterOut(getReadFirst(toRead, justRead), justRead); + assertEquals(1, Iterables.size(readNow)); + assertSame(parsed, Iterables.getFirst(readNow, null)); + Iterables.addAll(justRead, readNow); + + readNow = filterOut(getReadFirst(toRead, justRead), justRead); + assertEquals(0, Iterables.size(readNow)); + mExprModel.markBitsRead(); + assertEquals(0, Iterables.size(getShouldRead())); + } + + private List<Expr> filterOut(Iterable itr, final Iterable exclude) { + return Arrays.asList(Iterables.toArray(Iterables.filter(itr, new Predicate() { + @Override + public boolean apply(Object input) { + return !Iterables.contains(exclude, input); + } + }), Expr.class)); + } + + @Test public void testTernaryInsideTernary() { LayoutBinder lb = new MockLayoutBinder(); mExprModel = lb.getModel(); @@ -202,10 +261,12 @@ public class ExprModelTest { IdentifierExpr e = lb.addVariable("e", "java.lang.String"); final Expr aTernary = lb.parse("a == null ? b == null ? c : d : e"); assertTrue(aTernary instanceof TernaryExpr); - final Expr bTernary = ((TernaryExpr)aTernary).getIfTrue(); + final Expr bTernary = ((TernaryExpr) aTernary).getIfTrue(); assertTrue(bTernary instanceof TernaryExpr); - final Expr aIsNull = mExprModel.comparison("==", a, mExprModel.symbol("null", Object.class)); - final Expr bIsNull = mExprModel.comparison("==", b, mExprModel.symbol("null", Object.class)); + final Expr aIsNull = mExprModel + .comparison("==", a, mExprModel.symbol("null", Object.class)); + final Expr bIsNull = mExprModel + .comparison("==", b, mExprModel.symbol("null", Object.class)); lb.getModel().seal(); Iterable<Expr> shouldRead = getShouldRead(); // a and a == null @@ -217,7 +278,6 @@ public class ExprModelTest { assertTrue(d.getShouldReadFlags().isEmpty()); assertTrue(e.getShouldReadFlags().isEmpty()); - Iterable<Expr> readFirst = getReadFirst(shouldRead, null); assertEquals(1, Iterables.size(readFirst)); final Expr first = Iterables.getFirst(readFirst, null); @@ -267,7 +327,6 @@ public class ExprModelTest { LayoutBinder lb = new MockLayoutBinder(); mExprModel = lb.getModel(); - IdentifierExpr u1 = lb.addVariable("u1", User.class.getCanonicalName()); IdentifierExpr u2 = lb.addVariable("u2", User.class.getCanonicalName()); IdentifierExpr a = lb.addVariable("a", int.class.getCanonicalName()); @@ -276,7 +335,8 @@ public class ExprModelTest { IdentifierExpr d = lb.addVariable("d", int.class.getCanonicalName()); IdentifierExpr e = lb.addVariable("e", int.class.getCanonicalName()); TernaryExpr abTernary = parse(lb, "a > b ? u1.name : u2.name", TernaryExpr.class); - TernaryExpr bcTernary = parse(lb, "b > c ? u1.getCond(d) ? u1.lastName : u2.lastName : `xx` + u2.getCond(e) ", TernaryExpr.class); + TernaryExpr bcTernary = parse(lb, "b > c ? u1.getCond(d) ? u1.lastName : u2.lastName : `xx`" + + " + u2.getCond(e) ", TernaryExpr.class); Expr abCmp = abTernary.getPred(); Expr bcCmp = bcTernary.getPred(); Expr u1GetCondD = ((TernaryExpr) bcTernary.getIfTrue()).getPred(); @@ -287,7 +347,6 @@ public class ExprModelTest { Expr u1LastName = ((TernaryExpr) bcTernary.getIfTrue()).getIfTrue(); Expr u2LastName = ((TernaryExpr) bcTernary.getIfTrue()).getIfFalse(); - mExprModel.seal(); Iterable<Expr> shouldRead = getShouldRead(); @@ -314,8 +373,10 @@ public class ExprModelTest { assertFlags(d, bcTernary.getRequirementFlagIndex(true)); assertFlags(e, bcTernary.getRequirementFlagIndex(false)); - assertFlags(u1, bcTernary.getRequirementFlagIndex(true), abTernary.getRequirementFlagIndex(true)); - assertFlags(u2, bcTernary.getRequirementFlagIndex(false), abTernary.getRequirementFlagIndex(false)); + assertFlags(u1, bcTernary.getRequirementFlagIndex(true), + abTernary.getRequirementFlagIndex(true)); + assertFlags(u2, bcTernary.getRequirementFlagIndex(false), + abTernary.getRequirementFlagIndex(false)); assertFlags(u1GetCondD, bcTernary.getRequirementFlagIndex(true)); assertFlags(u2GetCondE, bcTernary.getRequirementFlagIndex(false)); @@ -342,8 +403,6 @@ public class ExprModelTest { assertFlags(bcTernary, b, c, u1, u2, d, u1LastName, u2LastName, e); } - - @Test public void testCircularDependency() { LayoutBinder lb = new MockLayoutBinder(); @@ -442,11 +501,13 @@ public class ExprModelTest { int i = 0; log("list", iterable); for (Expr expr : exprs) { - assertTrue((i++) + ":must contain " + expr.getUniqueKey(), Iterables.contains(iterable, expr)); + assertTrue((i++) + ":must contain " + expr.getUniqueKey(), + Iterables.contains(iterable, expr)); } i = 0; for (Expr expr : iterable) { - assertTrue((i++) + ":must be expected " + expr.getUniqueKey(), ArrayUtils.contains(exprs, expr)); + assertTrue((i++) + ":must be expected " + expr.getUniqueKey(), + ArrayUtils.contains(exprs, expr)); } } @@ -459,18 +520,16 @@ public class ExprModelTest { private void log(String s, Iterable<Expr> iterable) { L.d(s); for (Expr e : iterable) { - L.d(": %s : %s allFlags: %s readSoFar: %s", e.getUniqueKey(), e.getShouldReadFlags(), e.getShouldReadFlagsWithConditionals(), e.getReadSoFar()); + L.d(": %s : %s allFlags: %s readSoFar: %s", e.getUniqueKey(), e.getShouldReadFlags(), + e.getShouldReadFlagsWithConditionals(), e.getReadSoFar()); } L.d("end of %s", s); } -// private Iterable<Expr> getReadFirst(Iterable<Expr> shouldRead) { -// return mExprModel.filterCanBeReadNow(shouldRead); -// } - private Iterable<Expr> getReadFirst(Iterable<Expr> shouldRead) { return getReadFirst(shouldRead, null); } + private Iterable<Expr> getReadFirst(Iterable<Expr> shouldRead, final Iterable<Expr> justRead) { return Iterables.filter(shouldRead, new Predicate<Expr>() { @Override @@ -485,7 +544,9 @@ public class ExprModelTest { } public static class User { + String name; + String lastName; public String getName() { diff --git a/tools/data-binding/grammarBuilder/src/test/java/android/databinding/BindingExpressionParserTest.java b/tools/data-binding/grammarBuilder/src/test/java/android/databinding/BindingExpressionParserTest.java index 31f041f..9197ccf 100644 --- a/tools/data-binding/grammarBuilder/src/test/java/android/databinding/BindingExpressionParserTest.java +++ b/tools/data-binding/grammarBuilder/src/test/java/android/databinding/BindingExpressionParserTest.java @@ -1,23 +1,25 @@ package android.databinding; -import android.databinding.BindingExpressionParser.AndOrOpContext; -import android.databinding.BindingExpressionParser.BinaryOpContext; -import android.databinding.BindingExpressionParser.BindingSyntaxContext; -import android.databinding.BindingExpressionParser.BitShiftOpContext; -import android.databinding.BindingExpressionParser.ComparisonOpContext; -import android.databinding.BindingExpressionParser.DefaultsContext; -import android.databinding.BindingExpressionParser.DotOpContext; -import android.databinding.BindingExpressionParser.ExpressionContext; -import android.databinding.BindingExpressionParser.GroupingContext; -import android.databinding.BindingExpressionParser.LiteralContext; -import android.databinding.BindingExpressionParser.MathOpContext; -import android.databinding.BindingExpressionParser.PrimaryContext; -import android.databinding.BindingExpressionParser.PrimitiveTypeContext; -import android.databinding.BindingExpressionParser.QuestionQuestionOpContext; -import android.databinding.BindingExpressionParser.ResourceContext; -import android.databinding.BindingExpressionParser.StringLiteralContext; -import android.databinding.BindingExpressionParser.TernaryOpContext; -import android.databinding.BindingExpressionParser.UnaryOpContext; +import android.databinding.parser.BindingExpressionLexer; +import android.databinding.parser.BindingExpressionParser; +import android.databinding.parser.BindingExpressionParser.AndOrOpContext; +import android.databinding.parser.BindingExpressionParser.BinaryOpContext; +import android.databinding.parser.BindingExpressionParser.BindingSyntaxContext; +import android.databinding.parser.BindingExpressionParser.BitShiftOpContext; +import android.databinding.parser.BindingExpressionParser.ComparisonOpContext; +import android.databinding.parser.BindingExpressionParser.DefaultsContext; +import android.databinding.parser.BindingExpressionParser.DotOpContext; +import android.databinding.parser.BindingExpressionParser.ExpressionContext; +import android.databinding.parser.BindingExpressionParser.GroupingContext; +import android.databinding.parser.BindingExpressionParser.LiteralContext; +import android.databinding.parser.BindingExpressionParser.MathOpContext; +import android.databinding.parser.BindingExpressionParser.PrimaryContext; +import android.databinding.parser.BindingExpressionParser.PrimitiveTypeContext; +import android.databinding.parser.BindingExpressionParser.QuestionQuestionOpContext; +import android.databinding.parser.BindingExpressionParser.ResourceContext; +import android.databinding.parser.BindingExpressionParser.StringLiteralContext; +import android.databinding.parser.BindingExpressionParser.TernaryOpContext; +import android.databinding.parser.BindingExpressionParser.UnaryOpContext; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CommonTokenStream; diff --git a/tools/data-binding/integration-tests/TestApp/app/src/androidTest/java/android/databinding/testapp/InnerCannotReadDependencyTest.java b/tools/data-binding/integration-tests/TestApp/app/src/androidTest/java/android/databinding/testapp/InnerCannotReadDependencyTest.java new file mode 100644 index 0000000..68cf06b --- /dev/null +++ b/tools/data-binding/integration-tests/TestApp/app/src/androidTest/java/android/databinding/testapp/InnerCannotReadDependencyTest.java @@ -0,0 +1,49 @@ +/* + * 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 android.databinding.testapp; + +import android.databinding.testapp.databinding.InnerCannotReadDependencyBinding; +import android.databinding.testapp.vo.BasicObject; +import android.os.Debug; +import android.test.UiThreadTest; + +import org.junit.Test; + +public class InnerCannotReadDependencyTest extends + BaseDataBinderTest<InnerCannotReadDependencyBinding> { + + public InnerCannotReadDependencyTest() { + super(InnerCannotReadDependencyBinding.class); + } + + @UiThreadTest + public void testBinding() { + BasicObject object = new BasicObject(); + object.setField1("a"); + mBinder.setObj(object); + mBinder.executePendingBindings(); + assertEquals("a ", mBinder.textView.getText().toString()); + object.setField1(null); + mBinder.executePendingBindings(); + assertEquals("null ", mBinder.textView.getText().toString()); + object.setField2("b"); + mBinder.executePendingBindings(); + assertEquals("null b", mBinder.textView.getText().toString()); + object.setField1("c"); + mBinder.executePendingBindings(); + assertEquals("c b", mBinder.textView.getText().toString()); + } +} diff --git a/tools/data-binding/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/BasicObject.java b/tools/data-binding/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/BasicObject.java new file mode 100644 index 0000000..450f7fb --- /dev/null +++ b/tools/data-binding/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/BasicObject.java @@ -0,0 +1,45 @@ +/* + * 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 android.databinding.testapp.vo; +import android.databinding.BaseObservable; +import android.databinding.Bindable; +import android.databinding.testapp.BR; + +public class BasicObject extends BaseObservable { + @Bindable + private String mField1; + @Bindable + private String mField2; + + public String getField1() { + return mField1; + } + + public void setField1(String field1) { + this.mField1 = field1; + notifyPropertyChanged(BR.field1); + } + + public String getField2() { + return mField2; + } + + public void setField2(String field2) { + this.mField2 = field2; + notifyPropertyChanged(BR.field1); + } +} diff --git a/tools/data-binding/integration-tests/TestApp/app/src/main/res/layout/find_method_test.xml b/tools/data-binding/integration-tests/TestApp/app/src/main/res/layout/find_method_test.xml index c65ee39..33a3746 100644 --- a/tools/data-binding/integration-tests/TestApp/app/src/main/res/layout/find_method_test.xml +++ b/tools/data-binding/integration-tests/TestApp/app/src/main/res/layout/find_method_test.xml @@ -15,11 +15,11 @@ <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@{obj.method(1.25f}"/> + android:text="@{obj.method(1.25f)}"/> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@{obj.method(`hello`}"/> + android:text="@{obj.method(`hello`)}"/> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/tools/data-binding/integration-tests/TestApp/app/src/main/res/layout/inner_cannot_read_dependency.xml b/tools/data-binding/integration-tests/TestApp/app/src/main/res/layout/inner_cannot_read_dependency.xml new file mode 100644 index 0000000..2ad1980 --- /dev/null +++ b/tools/data-binding/integration-tests/TestApp/app/src/main/res/layout/inner_cannot_read_dependency.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="match_parent" + android:layout_height="match_parent"> + <variable name="obj" type="android.databinding.testapp.vo.BasicObject"/> + <TextView + android:id="@+id/text_view" + android:text='@{obj.field1 + " " + (obj.field2 ?? "")}' + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> +</LinearLayout>
\ No newline at end of file |