summaryrefslogtreecommitdiff
path: root/compiler/src/main/kotlin/android/databinding/tool
diff options
context:
space:
mode:
authorYigit Boyar <yboyar@google.com>2020-04-27 12:59:19 -0700
committerTreeHugger Robot <treehugger-gerrit@google.com>2020-04-30 19:10:41 +0000
commit754466f80a4aebc15e73abce4eb8b8358b516501 (patch)
tree291786058889c6ab7a8cb65d4cf82ec0eda86f53 /compiler/src/main/kotlin/android/databinding/tool
parent63d0ca4df6407dbbce9abc922a94e007acd4a6ed (diff)
downloaddata-binding-754466f80a4aebc15e73abce4eb8b8358b516501.tar.gz
Support included view binding in data binding
This CL fixes a couple of issues where data binding would generate wrong code by thinking an included layout also has data binding even when it only has view binding. To make the change least destructive, I've changed generated binding Impl to find view binding views via regular ids (as if they are views). After finding them, they are bound using GeneratedBindingClass.bind before passing it to the super class. Bug: 150397979 Test: ViewBindingWithDataBindingTestApp Change-Id: I445ce555a2629571447577f58d3d6ce075600fad
Diffstat (limited to 'compiler/src/main/kotlin/android/databinding/tool')
-rw-r--r--compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt32
1 files changed, 23 insertions, 9 deletions
diff --git a/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt b/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
index 64146c40..26b8203a 100644
--- a/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
+++ b/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
@@ -132,6 +132,16 @@ fun BindingTarget.superConversion(variable : String) : String {
return if (resolvedType != null && resolvedType.extendsViewStub) {
val libTypes = ModelAnalyzer.getInstance().libTypes
"new ${libTypes.viewStubProxy}((android.view.ViewStub) $variable)"
+ } else if(resolvedType != null && !resolvedType.isViewDataBinding && resolvedType.isViewBinding) {
+ // For included layouts, DataBinding used to rely on view tags we attach at compile time.
+ // For ViewBinding layouts, there is no such tag also no global inflate method
+ // (like DataBindingUtil.inflate). To workaround that issue, for <include> layouts with
+ // ViewBinding (no data binding), we find them as views and then bind here.
+ // see b/150397979 for details
+ "($variable != null) ? " +
+ "${resolvedType.toJavaCode()}.bind((android.view.View) $variable) " +
+ ": null"
+
} else {
"($interfaceClass) $variable"
}
@@ -172,6 +182,10 @@ val BindingTarget.constructorParamName by lazyProp { target: BindingTarget ->
target.model.getConstructorParamName(target.readableName)
}
+val BindingTarget.isDataBindingLayout:Boolean
+ get() = isBinder && resolvedType.isViewDataBinding
+
+
// not necessarily unique. Uniqueness is decided per scope
val Expr.readableName by lazyProp { expr: Expr ->
val stripped = expr.uniqueKey.stripNonJava()
@@ -332,7 +346,7 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder, val libTypes: LibTypes
val baseClassName = "${layoutBinder.className}"
val includedBinders by lazy {
- layoutBinder.bindingTargets.filter { it.isBinder }
+ layoutBinder.bindingTargets.filter { it.isDataBindingLayout }
}
val variables by lazy {
@@ -414,7 +428,7 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder, val libTypes: LibTypes
fun calculateIndices() {
val taggedViews = layoutBinder.bindingTargets.filter {
- it.isUsed && it.tag != null && !it.isBinder
+ it.isUsed && it.tag != null && !it.isDataBindingLayout
}
taggedViews.filter {
it.includedLayout == null
@@ -441,14 +455,14 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder, val libTypes: LibTypes
nl("@Nullable")
nl("private static final android.util.SparseIntArray sViewsWithIds;")
nl("static {") {
- val hasBinders = layoutBinder.bindingTargets.firstOrNull { it.isUsed && it.isBinder } != null
+ val hasBinders = layoutBinder.bindingTargets.any { it.isUsed && it.isDataBindingLayout }
if (!hasBinders) {
tab("sIncludes = null;")
} else {
val numBindings = layoutBinder.bindingTargets.filter { it.isUsed }.count()
tab("sIncludes = new ${libTypes.viewDataBinding}.IncludedLayouts($numBindings);")
val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
- layoutBinder.bindingTargets.filter { it.isUsed && it.isBinder }.forEach {
+ layoutBinder.bindingTargets.filter { it.isUsed && it.isDataBindingLayout }.forEach {
val includeTag = it.tag
val parent = layoutBinder.bindingTargets.firstOrNull {
it.isUsed && !it.isBinder && includeTag.equals(it.tag)
@@ -486,7 +500,7 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder, val libTypes: LibTypes
}
}
val viewsWithIds = layoutBinder.bindingTargets.filter {
- it.isUsed && !it.isBinder && (!it.supportsTag() || (it.id != null && (it.tag == null || it.includedLayout != null)))
+ it.isUsed && !it.isDataBindingLayout && (!it.supportsTag() || (it.id != null && (it.tag == null || it.includedLayout != null)))
}
if (viewsWithIds.isEmpty()) {
tab("sViewsWithIds = null;")
@@ -548,9 +562,6 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder, val libTypes: LibTypes
taggedViews.forEach {
if (!hasBaseBinder || it.id == null) {
tab("this.${it.fieldName} = ${fieldConversion(it)};")
- if (it.isBinder) {
- tab("setContainedBinding(this.${it.fieldName});")
- }
}
if (!it.isBinder) {
if (it.resolvedType != null && it.resolvedType.extendsViewStub) {
@@ -580,6 +591,9 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder, val libTypes: LibTypes
L.e(ErrorMessages.ROOT_TAG_NOT_SUPPORTED, it.originalTag)
}
}
+ if (it.isDataBindingLayout) {
+ tab("setContainedBinding(this.${it.fieldName});")
+ }
}
tab("setRootTag(root);")
tab(declareCallbackInstances())
@@ -1319,7 +1333,7 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder, val libTypes: LibTypes
tab("super(bindingComponent, root_, localFieldCount);")
layoutBinder.sortedTargets.filter{it.id != null}.forEach {
tab("this.${it.fieldName} = ${it.constructorParamName};")
- if (it.isBinder) {
+ if (it.isDataBindingLayout) {
tab("setContainedBinding(this.${it.fieldName});")
}
}