LayoutBinderWriter.kt revision 9e7a4ce47ae5f4428f7630fe03a7ad66d06177fb
1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/*
2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project
3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License.
5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at
6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software
8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and
11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License.
12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */
13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
14fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.writer
15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
16e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.BindingTarget
17716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.LayoutBinder
18fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel
20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.FieldAccessExpr
21716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.expr.IdentifierExpr
22793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport android.databinding.tool.expr.ListenerExpr
23716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.expr.TernaryExpr
247b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.androidId
257b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.br
267b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.joinToCamelCaseAsVar
27716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.ext.lazy
28716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.ext.versionedLazy
2992a428505b9102bc0560d2d5be1768da097909c2George Mountimport android.databinding.tool.processing.ErrorMessages
30fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer
317b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.util.L
3296e1c821dd446d1ed78f8ae61131550588f60a24George Mountimport java.util.ArrayList
33716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport java.util.Arrays
34716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport java.util.BitSet
3534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.HashMap
36716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport kotlin.properties.Delegates
3743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
38fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]".toRegex()).map{ it.trim() }.joinToCamelCaseAsVar()
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
40019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarenum class Scope {
41fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    FIELD,
42fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    METHOD,
43fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    FLAG,
44fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    EXECUTE_PENDING_METHOD,
45019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    CONSTRUCTOR_PARAM
46019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar}
47019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
49019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val usedFieldNames = hashMapOf<Scope, MutableSet<String>>();
50fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    init {
51019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        Scope.values().forEach { usedFieldNames[it] = hashSetOf<String>() }
52019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    }
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val localizedFlags = arrayListOf<FlagSet>()
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun localizeFlag(set : FlagSet, name:String) : FlagSet {
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        localizedFlags.add(set)
57793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        val result = getUniqueName(name, Scope.FLAG, false)
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        set.setLocalName(result)
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return set
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
62793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    fun getUniqueName(base : String, scope : Scope, isPublic : kotlin.Boolean) : String {
63793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        var candidateBase = base
64793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        if (!isPublic && candidateBase.length() > 20) {
65793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            candidateBase = candidateBase.substring(0, 20);
66793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        }
67793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        var candidate = candidateBase
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var i = 0
69019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        while (usedFieldNames[scope].contains(candidate)) {
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            i ++
71793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            candidate = candidateBase + i
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
73019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        usedFieldNames[scope].add(candidate)
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return candidate
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
78de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval ExprModel.ext by Delegates.lazy { target : ExprModel ->
79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    ExprModelExt()
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
81d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
82793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountfun ExprModel.getUniqueFieldName(base : String, isPublic : kotlin.Boolean) : String = ext.getUniqueName(base, Scope.FIELD, isPublic)
83793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountfun ExprModel.getUniqueMethodName(base : String, isPublic : kotlin.Boolean) : String = ext.getUniqueName(base, Scope.METHOD, isPublic)
84793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountfun ExprModel.getUniqueFlagName(base : String) : String = ext.getUniqueName(base, Scope.FLAG, false)
85793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountfun ExprModel.getConstructorParamName(base : String) : String = ext.getUniqueName(base, Scope.CONSTRUCTOR_PARAM, false)
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
89019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// not necessarily unique. Uniqueness is solved per scope
90019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.readableName by Delegates.lazy { target: BindingTarget ->
9100da715547ee7d5d38a3b8576090ca427a94daa5George Mount    if (target.getId() == null) {
92019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        "boundView" + indexFromTag(target.getTag())
9300da715547ee7d5d38a3b8576090ca427a94daa5George Mount    } else {
94019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        target.getId().androidId().stripNonJava()
9500da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
96d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
977551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
98de38dd3ef0577d25b2d59863603abe5750d0c231George Mountfun BindingTarget.superConversion(variable : String) : String {
9996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    if (getResolvedType() != null && getResolvedType().extendsViewStub()) {
100de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "new android.databinding.ViewStubProxy((android.view.ViewStub) ${variable})"
101de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
102de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "(${interfaceType}) ${variable}"
103de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
104de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
105de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
106019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.fieldName : String by Delegates.lazy { target : BindingTarget ->
107019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val name : String
108793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    val isPublic : kotlin.Boolean
109019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    if (target.getId() == null) {
110019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        name = "m${target.readableName}"
111793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        isPublic = false
112019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    } else {
113019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        name = target.readableName
114793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        isPublic = true
11534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
116793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    target.getModel().getUniqueFieldName(name, isPublic)
117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
119de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.androidId by Delegates.lazy { target : BindingTarget ->
120fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount    if (target.getId().startsWith("@android:id/")) {
121fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount        "android.R.id.${target.getId().androidId()}"
122fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount    } else {
123fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount        "R.id.${target.getId().androidId()}"
124fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount    }
125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
127de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.interfaceType by Delegates.lazy { target : BindingTarget ->
128de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    if (target.getResolvedType() != null && target.getResolvedType().extendsViewStub()) {
129de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        "android.databinding.ViewStubProxy"
130de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
131de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        target.getInterfaceType()
132de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
133de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
134de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
135019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.constructorParamName by Delegates.lazy { target : BindingTarget ->
136019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    target.getModel().getConstructorParamName(target.readableName)
137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
139019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// not necessarily unique. Uniqueness is decided per scope
140de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableName by Delegates.lazy { expr : Expr ->
141019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val stripped = "${expr.getUniqueKey().stripNonJava()}"
142b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar    L.d("readableUniqueName for [%s] %s is %s", System.identityHashCode(expr), expr.getUniqueKey(), stripped)
143019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    stripped
144de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
145de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
146de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.fieldName by Delegates.lazy { expr : Expr ->
147793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    expr.getModel().getUniqueFieldName("m${expr.readableName.capitalize()}", false)
148d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
150716ba89e7f459f49ea85070d4710c1d79d715298George Mountval Expr.listenerClassName by Delegates.lazy { expr : Expr ->
151793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    expr.getModel().getUniqueFieldName("${expr.getResolvedType().getSimpleName()}Impl", false)
152716ba89e7f459f49ea85070d4710c1d79d715298George Mount}
153716ba89e7f459f49ea85070d4710c1d79d715298George Mount
15420c7182163d99575d382e065f5a5fe45ed6b87e2George Mountval Expr.oldValueName by Delegates.lazy { expr : Expr ->
155793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    expr.getModel().getUniqueFieldName("mOld${expr.readableName.capitalize()}", false)
15620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount}
15720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
158019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval Expr.executePendingLocalName by Delegates.lazy { expr : Expr ->
159793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    "${expr.getModel().ext.getUniqueName(expr.readableName, Scope.EXECUTE_PENDING_METHOD, false)}"
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
162de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.setterName by Delegates.lazy { expr : Expr ->
163793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    expr.getModel().getUniqueMethodName("set${expr.readableName.capitalize()}", true)
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
166de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.onChangeName by Delegates.lazy { expr : Expr ->
167793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    expr.getModel().getUniqueMethodName("onChange${expr.readableName.capitalize()}", false)
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
170de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.getterName by Delegates.lazy { expr : Expr ->
171793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    expr.getModel().getUniqueMethodName("get${expr.readableName.capitalize()}", true)
172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
174de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagName by Delegates.lazy { expr : Expr ->
175019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueFlagName("sFlag${expr.readableName.capitalize()}")
176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
183de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagSet by Delegates.lazy { expr : Expr ->
184d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
187de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagSet by Delegates.lazy { expr : Expr ->
188d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getId())
189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
1917b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarval Expr.shouldReadFlagSet by Delegates.versionedLazy { expr : Expr ->
192d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
195de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlags by Delegates.lazy { expr : Expr ->
196d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
197d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
199d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
200e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mountval LayoutBinder.requiredComponent by Delegates.lazy { layoutBinder: LayoutBinder ->
201e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    val required = layoutBinder.
202e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            getBindingTargets().
203e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            flatMap { it.getBindings() }.
204e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            firstOrNull { it.getBindingAdapterInstanceClass() != null }
205e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    required?.getBindingAdapterInstanceClass()
206e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount}
207e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
217d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
218d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
219d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
220d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
221d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
222d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
223d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (getLocalName() == null) binaryCode(bucketIndex)
224d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
225d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
226d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
227d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
228d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
229d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun longToBinary(l : Long) =
230d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        "0b${java.lang.Long.toBinaryString(l)}L"
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
238d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
239d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
240d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
241d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
242d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
243d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
24496e1c821dd446d1ed78f8ae61131550588f60a24George Mountfun indexFromTag(tag : String) : kotlin.Int {
24596e1c821dd446d1ed78f8ae61131550588f60a24George Mount    val startIndex : kotlin.Int
2467ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    if (tag.startsWith("binding_")) {
2477ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        startIndex = "binding_".length();
24896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    } else {
24996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        startIndex = tag.lastIndexOf('_') + 1
25096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
25196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    return Integer.parseInt(tag.substring(startIndex))
25296e1c821dd446d1ed78f8ae61131550588f60a24George Mount}
25396e1c821dd446d1ed78f8ae61131550588f60a24George Mount
25443596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
25634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
25743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
25843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
25943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
26043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
26143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
26243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
263d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
264d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
26543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
266dea555cf42dc3583604699c8c018d22681f56166George Mount    val className = layoutBinder.getImplementationName()
267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
268dea555cf42dc3583604699c8c018d22681f56166George Mount    val baseClassName = "${layoutBinder.getClassName()}"
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2707551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
2717551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
2727551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
2737551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
27443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
27543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
27643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2785bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
2795bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
2805bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
281d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
28296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public fun write(minSdk : kotlin.Int) : String  {
2835bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
28434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
2855bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
286a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
287a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
2885bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
289dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
290dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
291dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends ${baseClassName}"
292dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
293dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends android.databinding.ViewDataBinding"
294dea555cf42dc3583604699c8c018d22681f56166George Mount            }
295dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public class ${classDeclaration} {") {
2964c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
2975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
2985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
29920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                tab(declareBoundValues())
300716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab(declareListeners())
30196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab(declareConstructor(minSdk))
3025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
303447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab(declareHasPendingBindings())
3045bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
3055bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
3065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
3075bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3085bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3094c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
311716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab(declareListenerImpls())
3125bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
313dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
314dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
315dea555cf42dc3583604699c8c018d22681f56166George Mount                }
3165bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3175bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3185bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3195bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3205bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3215bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
32234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
32396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getBindingTargets().filter{
324d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount            it.isUsed() && it.getTag() != null && !it.isBinder()
32534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
32696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        taggedViews.forEach {
32796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it, indexFromTag(it.getTag()))
32896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
32996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val indexStart = maxIndex() + 1
33096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getBindingTargets().filter{
33196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && !taggedViews.contains(it)
33296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }.withIndex().forEach {
33396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it.value, it.index + indexStart)
33434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
33534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
3364c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
337239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        nl("private static final android.databinding.ViewDataBinding.IncludedLayouts sIncludes;")
3384c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
3394c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
3404c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
3414c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
3424c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
34300da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
34496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val numBindings = layoutBinder.getBindingTargets().filter{ it.isUsed() }.count()
345239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                tab("sIncludes = new android.databinding.ViewDataBinding.IncludedLayouts(${numBindings});")
34696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
34796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder() }.forEach {
34896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val includeTag = it.getTag();
34996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val parent = layoutBinder.getBindingTargets().firstOrNull {
35096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        it.isUsed() && !it.isBinder() && includeTag.equals(it.getTag())
35196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
35296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (parent == null) {
35396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        throw IllegalStateException("Could not find parent of include file")
35496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
35596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    var list = includeMap.get(parent)
35696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (list == null) {
35796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        list = ArrayList<BindingTarget>()
35896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.put(parent, list)
35996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
36096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    list.add(it)
3614c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
36296e1c821dd446d1ed78f8ae61131550588f60a24George Mount
36396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                includeMap.keySet().forEach {
36496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val index = indices.get(it)
365239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                    tab("sIncludes.setIncludes(${index}, ") {
366239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab ("new String[] {${
367239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
368239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "\"${it.getIncludedLayout()}\""
369239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
370239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }},")
371239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab("new int[] {${
372239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
373239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "${indices.get(it)}"
374239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
375239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }},")
376239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab("new int[] {${
377239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
378239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "R.layout.${it.getIncludedLayout()}"
379239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
380239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }});")
38196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
38296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
38396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
38496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val viewsWithIds = layoutBinder.getBindingTargets().filter {
385d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount                it.isUsed() && !it.isBinder() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
38600da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
38796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (viewsWithIds.isEmpty()) {
3884c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
38900da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
3904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
39196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                viewsWithIds.forEach {
39234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sViewsWithIds.put(${it.androidId}, ${indices.get(it)});")
3934c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
39400da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
3954c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
3964c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
3974c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
39896e1c821dd446d1ed78f8ae61131550588f60a24George Mount
39996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun maxIndex() : kotlin.Int {
40096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val maxIndex = indices.values().max()
40196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (maxIndex == null) {
40296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return -1
40396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
40496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return maxIndex
40596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
40696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
40796e1c821dd446d1ed78f8ae61131550588f60a24George Mount
40896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun declareConstructor(minSdk : kotlin.Int) = kcode("") {
40996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val bindingCount = maxIndex() + 1
41096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val parameterType : String
41196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val superParam : String
41296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (layoutBinder.isMerge()) {
41396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View[]"
41496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root[0]"
41596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
41696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View"
41796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root"
41896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
41996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val rootTagsSupported = minSdk >= 14
420dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
421dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
422e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public ${className}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root) {") {
423e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("this(bindingComponent, ${superParam}, mapBindings(bindingComponent, root, ${bindingCount}, sIncludes, sViewsWithIds));")
424dea555cf42dc3583604699c8c018d22681f56166George Mount            }
425dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
426e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("private ${className}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root, Object[] bindings) {") {
427e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, ${superParam}, ${model.getObservables().size()}") {
42896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    layoutBinder.getSortedTargets().filter { it.getId() != null }.forEach {
429dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
43034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
431dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
43234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
43334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
434dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
435e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public ${baseClassName}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root) {") {
436e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, ${superParam}, ${model.getObservables().size()});")
437e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("final Object[] bindings = mapBindings(bindingComponent, root, ${bindingCount}, sIncludes, sViewsWithIds);")
438dea555cf42dc3583604699c8c018d22681f56166George Mount            }
439dea555cf42dc3583604699c8c018d22681f56166George Mount        }
440e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        if (layoutBinder.requiredComponent != null) {
441e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("ensureBindingComponentIsNotNull(${layoutBinder.requiredComponent}.class);")
442e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
44396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getSortedTargets().filter{it.isUsed()}
444dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
445dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!layoutBinder.hasVariations() || it.getId() == null) {
446dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
447dea555cf42dc3583604699c8c018d22681f56166George Mount            }
448d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount            if (!it.isBinder()) {
449de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                if (it.getResolvedType() != null && it.getResolvedType().extendsViewStub()) {
450de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
451de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
45296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (it.supportsTag() && it.getTag() != null &&
4537ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        (rootTagsSupported || it.getTag().startsWith("binding_"))) {
454dea555cf42dc3583604699c8c018d22681f56166George Mount                    val originalTag = it.getOriginalTag();
455dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
45692a428505b9102bc0560d2d5be1768da097909c2George Mount                    if (originalTag != null && !originalTag.startsWith("@{")) {
457dea555cf42dc3583604699c8c018d22681f56166George Mount                        tagValue = "\"${originalTag}\""
458dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
459dea555cf42dc3583604699c8c018d22681f56166George Mount                            var packageName = layoutBinder.getModulePackage()
460dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
461dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
46200da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
463dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
464dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
465dea555cf42dc3583604699c8c018d22681f56166George Mount                            tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
46600da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
46700da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
468dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab("this.${it.fieldName}.setTag(${tagValue});")
46992a428505b9102bc0560d2d5be1768da097909c2George Mount                } else if (it.getTag() != null && !it.getTag().startsWith("binding_") &&
47092a428505b9102bc0560d2d5be1768da097909c2George Mount                    it.getOriginalTag() != null) {
47192a428505b9102bc0560d2d5be1768da097909c2George Mount                    L.e(ErrorMessages.ROOT_TAG_NOT_SUPPORTED, it.getOriginalTag())
4727551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
473d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
474d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4754d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount        tab("setRootTag(root);")
476dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
4770fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
478d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
479d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
480dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
481dea555cf42dc3583604699c8c018d22681f56166George Mount        if (!target.isUsed()) {
482dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
483dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
48496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val index = indices.get(target)
485dea555cf42dc3583604699c8c018d22681f56166George Mount            if (index == null) {
48696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                throw IllegalStateException("Unknown binding target")
487dea555cf42dc3583604699c8c018d22681f56166George Mount            }
48896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val variableName = "bindings[${index}]"
489dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
490dea555cf42dc3583604699c8c018d22681f56166George Mount        }
491dea555cf42dc3583604699c8c018d22681f56166George Mount    }
492dea555cf42dc3583604699c8c018d22681f56166George Mount
493d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
4947551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
4957551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
496019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            val fs = FlagSet(layoutBinder.getModel().getInvalidateAnyBitSet(),
497019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    layoutBinder.getModel().getFlagBucketCount());
4981c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
4991c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
5001c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
5011c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
5021c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
5035bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
5047551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
5057551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
5062f64c44e4fa296cf658ca986c095eab62f82a31dYigit Boyar            tab("requestRebind();");
507d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5080fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
509d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
510d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
511447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    fun declareHasPendingBindings()  = kcode("") {
512447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("@Override")
513447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("public boolean hasPendingBindings() {") {
514447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            if (mDirtyFlags.buckets.size() > 0) {
515447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("synchronized(this) {") {
516447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    val flagCheck = 0.rangeTo(mDirtyFlags.buckets.size() - 1).map {
517447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                            "${mDirtyFlags.localValue(it)} != 0"
518447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }.joinToString(" || ")
519447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("if (${flagCheck}) {") {
520447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                        tab("return true;")
521447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }
522447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("}")
523447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
524447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
525447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
526447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            includedBinders.filter{it.isUsed()}.forEach { binder ->
527447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("if (${binder.fieldName}.hasPendingBindings()) {") {
528447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("return true;")
529447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
530447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
531447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
532447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            tab("return false;")
533447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        }
534447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("}")
535447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    }
536447971abca811b11b8c1d8e7bfaa294856d03c16George Mount
537d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
5380fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
539d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
5405bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
54143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab ("case ${it.getName().br()} :") {
542d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);")
543d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
544d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
545d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
546d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
547d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
548d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
549d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5500fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
551d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
552d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
553d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareLog() = kcode("") {
5540fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("private void log(String msg, long i) {") {
555d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""")
5560fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        }
5570fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
558d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
559d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
560d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
5615bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filterNot{it.isUsed()}.forEach {
562019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
5635bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
5645bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5655bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5665bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
5675bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
5685bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("return ${it.getDefaultValue()};")
5695bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5705bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5715bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
5725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
57318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount            if (it.getUserDefinedType() != null) {
574019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
57518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
576019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                        tab("updateRegistration(${it.getId()}, ${it.readableName});");
57718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
578019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.readableName};")
57918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
58018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
5811c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("synchronized(this) {") {
5821c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
5831c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
5841c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        }
5851c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    } tab ("}")
58618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
58818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
58918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
59018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
59118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
592d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
59318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
594d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
596d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
597d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
598d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
59934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
60034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
6014c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
602d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
603d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
604d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
605d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
606d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
607d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
608d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
609d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
610d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
61134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
61234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
613d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
614d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
615019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableName}, int fieldId) {") {
616d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
617d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
618c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount                    accessedFields.filter { it.hasBindableAnnotations() }
619d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
620d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
62143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
622d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
6231c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    tab("synchronized(this) {") {
6241c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
6251c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                            tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
6261c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        }
6271c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    } tab("}")
628d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
629d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
630d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
63243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
633d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
6341c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        tab("synchronized(this) {") {
6351c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            mDirtyFlags.mapOr(flagSet) { suffix, index ->
6361c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
6371c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            }
6381c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        } tab("}")
639d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
640d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
641d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
642d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
643d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
644d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
645d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
64634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
64734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
648d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
649d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
650d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
651d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
652dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
65396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getSortedTargets().filter {it.isUsed() && (oneLayout || it.getId() == null)}.forEach {
654dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
655dea555cf42dc3583604699c8c018d22681f56166George Mount            if (oneLayout && it.getId() != null) {
656dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
657dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
658dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
659dea555cf42dc3583604699c8c018d22681f56166George Mount            }
660dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${access} final ${it.interfaceType} ${it.fieldName};")
661d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
662d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
663d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
664d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
6655bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
6660fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
667d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
668d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
669d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
67020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    fun declareBoundValues() = kcode("// values") {
67120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        layoutBinder.getSortedTargets().filter { it.isUsed() }
67220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .flatMap { it.getBindings() }
67320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .filter { it.requiresOldValue() }
67420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .flatMap{ it.getComponentExpressions().toArrayList() }
67520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .groupBy { it }
67620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .forEach {
67720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    val expr = it.getKey()
67820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    nl("private ${expr.getResolvedType().toJavaCode()} ${expr.oldValueName};")
67920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                }
68020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    }
68120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
682716ba89e7f459f49ea85070d4710c1d79d715298George Mount    fun declareListeners() = kcode("// listeners") {
683716ba89e7f459f49ea85070d4710c1d79d715298George Mount        model.getExprMap().values().filter {
684793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            it is ListenerExpr
685716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }.groupBy { it }.forEach {
686793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            val expr = it.key as ListenerExpr
687716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("private ${expr.listenerClassName} ${expr.fieldName};")
688716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
689716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
690716ba89e7f459f49ea85070d4710c1d79d715298George Mount
691d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
692d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
693de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
6940fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
695d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
696d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = ${longToBinary(value)};")
697d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
698d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
699d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
700d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
701d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
702d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
703d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
704d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
705d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
706d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
707d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
708d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
709d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
710d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7114c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
7120fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
713e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        nl("protected void executeBindings() {") {
714d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
715d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
716d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
7171c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = 0;")
718d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
7191c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
7201c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..mDirtyFlags.buckets.size() - 1)) {
7211c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
7221c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = 0;")
7231c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
7241c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
725a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            model.getPendingExpressions().filterNot { !it.canBeEvaluatedToAVariable() || (it.isVariable() && !it.isUsed()) }.forEach {
726a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("${it.getResolvedType().toJavaCode()} ${it.executePendingLocalName} = ${if (it.isVariable()) it.fieldName else it.getDefaultValue()};")
727d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
728b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar            L.d("writing executePendingBindings for %s", className)
729d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
73074f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
731a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                val justRead = arrayListOf<Expr>()
732b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                L.d("batch: %s", batch)
733d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
734a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val readNow = batch.filter { it.shouldReadNow(justRead) }
735d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
736d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
737d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
738b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                    L.d("new read now. batch size: %d, readNow size: %d", batch.size(), readNow.size())
739a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    nl(readWithDependants(readNow, justRead, batch, tmpDirtyFlags))
740a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    batch.removeAll(justRead)
741d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7420fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
743a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } while (model.markBitsRead())
7447b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            // verify everything is read.
7457b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
7467b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            if (batch.isNotEmpty()) {
7477b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                L.e("could not generate code for %s. This might be caused by circular dependencies."
748e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount                        + "Please report on b.android.com. %d %s %s", layoutBinder.getLayoutname(),
749e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount                        batch.size(), batch.get(0), batch.get(0).toCode().generate())
7507b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            }
751d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
75296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
753d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
754a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    .groupBy {
755a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        "${tmpDirtyFlags.mapOr(it.getExpr().dirtyFlagSet) { suffix, index ->
756a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            "(${tmpDirtyFlags.localValue(index)} & ${it.getExpr().dirtyFlagSet.localValue(index)}) != 0"
757a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }.joinToString(" || ") }"
758a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }.forEach {
759a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("if (${it.key}) {") {
760a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    it.value.groupBy { Math.max(1, it.getMinApi()) }.forEach {
761a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val setterValues = kcode("") {
762d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
763a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                val fieldName: String
764d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount                                if (binding.getTarget().getViewClass().
76534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                        equals(binding.getTarget().getInterfaceType())) {
76634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "this.${binding.getTarget().fieldName}"
76734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
76834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "((${binding.getTarget().getViewClass()}) this.${binding.getTarget().fieldName})"
76934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
770a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                tab(binding.toJavaCode(fieldName, "this.mBindingComponent")).app(";")
771a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
772a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
773a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        tab("// api target ${it.key}")
774a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (it.key > 1) {
775a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("if(getBuildSdkInt() >= ${it.key}) {") {
776a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                app("", setterValues)
777d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
778a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("}")
779a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        } else {
780a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            app("", setterValues)
78120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }
78220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    }
783a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
784a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
785a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }
786a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
78720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
78820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
78920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .flatMap { it.getBindings() }
79020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .filter { it.requiresOldValue() }
791a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    .groupBy {"${tmpDirtyFlags.mapOr(it.getExpr().dirtyFlagSet) { suffix, index ->
792a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        "(${tmpDirtyFlags.localValue(index)} & ${it.getExpr().dirtyFlagSet.localValue(index)}) != 0"
793a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }.joinToString(" || ")
794a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }"}.forEach {
795a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("if (${it.key}) {") {
796a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    it.value.groupBy { it.getExpr() }.map { it.value.first() }.forEach {
797a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        it.getComponentExpressions().forEach { expr ->
798a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("this.${expr.oldValueName} = ${expr.toCode().generate()};")
799d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
800d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
801a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
802a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
803a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }
8045bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
8054c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
8067551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
80796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{
808de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                it.isUsed() && it.getResolvedType() != null && it.getResolvedType().extendsViewStub()
809de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }.forEach {
810de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("if (${it.fieldName}.getBinding() != null) {") {
811de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("${it.fieldName}.getBinding().executePendingBindings();")
812de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
813de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("}")
814de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
815d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
8160fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
817d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
818d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
819a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    fun readWithDependants(expressionList: List<Expr>, justRead: MutableList<Expr>,
820a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            batch: MutableList<Expr>, tmpDirtyFlags: FlagSet,
821a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            inheritedFlags: FlagSet? = null) : KCode = kcode("") {
822a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount        expressionList.groupBy { it.shouldReadFlagSet }.forEach {
823a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val flagSet = it.key
824a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
825a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val expressions = it.value
826a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
827a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
828a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }.joinToString(" || ")
829a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            })"
830a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val readCode = kcode("") {
831a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                val dependants = ArrayList<Expr>()
832a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                expressions.groupBy { condition(it) }.forEach {
833a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val condition = it.key
834a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val assignedValues = it.value.filter {
835a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        it.canBeEvaluatedToAVariable() && !it.isVariable()
836d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
837a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    if (!assignedValues.isEmpty()) {
838a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val assignment = kcode("") {
839a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            assignedValues.forEach { expr: Expr ->
840a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                tab("// read ${expr.getUniqueKey()}")
841a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                tab("${expr.executePendingLocalName}").app(" = ", expr.toFullCode()).app(";")
842a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
843a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
844a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (condition != null) {
845a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("if (${condition}) {") {
846a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                app("", assignment)
847a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
848a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab ("}")
849a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        } else {
850a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            app("", assignment)
851d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
8529e7a4ce47ae5f4428f7630fe03a7ad66d06177fbGeorge Mount                        it.value.filter { it.isObservable() }.forEach { expr: Expr ->
8539e7a4ce47ae5f4428f7630fe03a7ad66d06177fbGeorge Mount                            tab("updateRegistration(${expr.getId()}, ${expr.executePendingLocalName});")
8549e7a4ce47ae5f4428f7630fe03a7ad66d06177fbGeorge Mount                        }
855a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }
856a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
857a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    it.value.forEach { expr: Expr ->
858a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        justRead.add(expr)
859a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        L.d("%s / readWithDependants %s", className, expr.getUniqueKey());
860a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        L.d("flag set:%s . inherited flags: %s. need another if: %s", flagSet, inheritedFlags, needsIfWrapper);
861a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
862a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        // if I am the condition for an expression, set its flag
863a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val conditionals = expr.getDependants().filter {
864a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            !it.isConditional() && it.getDependant() is TernaryExpr &&
865a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    (it.getDependant() as TernaryExpr).getPred() == expr
866a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }.map { it.getDependant() }
867a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (conditionals.isNotEmpty()) {
868a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("// setting conditional flags")
869a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("if (${expr.executePendingLocalName}) {") {
870a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                conditionals.forEach {
871a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    val set = it.getRequirementFlagSet(true)
872a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    mDirtyFlags.mapOr(set) { suffix, index ->
873a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                        tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
874a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    }
875a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                }
876a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
877a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("} else {") {
878a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                conditionals.forEach {
879a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    val set = it.getRequirementFlagSet(false)
880a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    mDirtyFlags.mapOr(set) { suffix, index ->
881a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                        tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
882a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    }
883a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                }
884a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
885a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("}")
886a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
887a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
888a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val chosen = expr.getDependants().filter {
889a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            val dependant = it.getDependant()
890a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            batch.contains(dependant) &&
891a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    dependant.shouldReadFlagSet.andNot(flagSet).isEmpty() &&
892a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    dependant.shouldReadNow(justRead)
893a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
894a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (chosen.isNotEmpty()) {
895a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            dependants.addAll(chosen.map { it.getDependant() })
8960fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
8970fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
898a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
899a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                if (dependants.isNotEmpty()) {
900a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
901a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    nl(readWithDependants(dependants, justRead, batch, tmpDirtyFlags, nextInheritedFlags))
902a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
903d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
9040fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
905a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            if (needsIfWrapper) {
906a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab(ifClause) {
907a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    app(" {")
908a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    app("", readCode)
909d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
910a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
911a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } else {
912a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                app("", readCode)
913d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
914d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
915a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    }
916a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
917a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    fun condition(expr : Expr) : String? {
918a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount        if (expr.canBeEvaluatedToAVariable() && !expr.isVariable()) {
919a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            // create an if case for all dependencies that might be null
920a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val nullables = expr.getDependencies().filter {
921a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                it.isMandatory() && it.getOther().getResolvedType().isNullable()
922a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }.map { it.getOther() }
923a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
924a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                return "${nullables.map { "${it.executePendingLocalName} != null" }.joinToString(" && ")}"
925a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } else {
926a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                return null
927d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
928d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
929a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            return null
930d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
931d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
932716ba89e7f459f49ea85070d4710c1d79d715298George Mount
933716ba89e7f459f49ea85070d4710c1d79d715298George Mount    fun declareListenerImpls() = kcode("// Listener Stub Implementations") {
934716ba89e7f459f49ea85070d4710c1d79d715298George Mount        model.getExprMap().values().filter {
935793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            it.isUsed() && it is ListenerExpr
936716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }.groupBy { it }.forEach {
937793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            val expr = it.key as ListenerExpr
938793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            val listenerType = expr.getResolvedType();
939793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            val extendsImplements : String
940793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            if (listenerType.isInterface()) {
941793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                extendsImplements = "implements"
942793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            } else {
943793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                extendsImplements = "extends"
944793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            }
945793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            nl("public static class ${expr.listenerClassName} ${extendsImplements} ${listenerType.getCanonicalName()}{") {
946716ba89e7f459f49ea85070d4710c1d79d715298George Mount                if (expr.getChild().isDynamic()) {
947716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("private ${expr.getChild().getResolvedType().toJavaCode()} value;")
948716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("public ${expr.listenerClassName} setValue(${expr.getChild().getResolvedType().toJavaCode()} value) {") {
949716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("this.value = value;")
950716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("return value == null ? null : this;")
951716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }
952716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("}")
953716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
954793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                val listenerMethod = expr.getMethod()
955793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                val parameterTypes = listenerMethod.getParameterTypes()
956793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                val returnType = listenerMethod.getReturnType(parameterTypes.toArrayList())
957793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                tab("@Override")
958793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                tab("public ${returnType} ${listenerMethod.getName()}(${
959716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    parameterTypes.withIndex().map {
960716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        "${it.value.toJavaCode()} arg${it.index}"
961716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }.joinToString(", ")
962793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                }) {") {
963793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    val obj : String
964793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    if (expr.getChild().isDynamic()) {
965793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        obj = "this.value"
966793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    } else {
967793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        obj = expr.getChild().toCode().generate();
968793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    }
969793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    val returnStr : String
970793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    if (!returnType.isVoid()) {
971793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        returnStr = "return "
972793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    } else {
973793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        returnStr = ""
974716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }
975793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    val args = parameterTypes.withIndex().map {
976793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        "arg${it.index}"
977793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    }.joinToString(", ")
978793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    tab("${returnStr}${obj}.${expr.getName()}(${args});")
979716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
980793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                tab("}")
981716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
982716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("}")
983716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
984716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
98543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
986dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
987081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
988e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
989e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
990e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        nl("}")
991e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
992e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("return android.databinding.DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot, bindingComponent);")
993081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        }
994081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("}")
99596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (!layoutBinder.isMerge()) {
996081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount            nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
997e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
998e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
999e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("}")
1000e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
1001e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return bind(inflater.inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false), bindingComponent);")
100296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
100396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
100496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} bind(android.view.View view) {") {
1005e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
1006e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1007e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("}")
1008e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public static ${baseClassName} bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
100996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("if (!\"${layoutBinder.getTag()}_0\".equals(view.getTag())) {") {
1010f80b08430f11515ff944f89006799f21545602b9George Mount                    tab("throw new RuntimeException(\"view tag isn't correct on view:\" + view.getTag());")
101196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
101296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("}")
1013e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return new ${baseClassName}(bindingComponent, view);")
101496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
101596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
1016dea555cf42dc3583604699c8c018d22681f56166George Mount        }
1017dea555cf42dc3583604699c8c018d22681f56166George Mount    }
1018dea555cf42dc3583604699c8c018d22681f56166George Mount
10198b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    /**
10208b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar     * When called for a library compilation, we do not generate real implementations
10218b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar     */
10228b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    public fun writeBaseClass(forLibrary : Boolean) : String =
102343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
1024fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
1025fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
1026fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
10274c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
102896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
1029de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("public final ${it.interfaceType} ${it.fieldName};")
103034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
103134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
1032e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("protected ${baseClassName}(android.databinding.DataBindingComponent bindingComponent, android.view.View root_, int localFieldCount") {
103396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
1034019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab(", ${it.interfaceType} ${it.constructorParamName}")
103534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
103634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
103734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
1038e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, root_, localFieldCount);")
103996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
1040019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.constructorParamName};")
104134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
10424c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10434c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
10444c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
104543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
104618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
1047895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
1048019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("public abstract void ${it.setterName}(${type} ${it.readableName});")
104918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
105043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
10519bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
1052e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
1053e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1054e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1055e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
1056e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
1057e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1058e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1059e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
10608b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10618b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10628b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1063e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
10648b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
106543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
10664c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
1067e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
10688b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10698b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10708b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1071e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot, bindingComponent);")
10728b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
10734c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10744c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
1075e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
1076e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                if (forLibrary) {
1077e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return null;")
1078e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                } else {
1079e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false, bindingComponent);")
1080e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                }
1081e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1082e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1083e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
10848b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10858b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10868b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1087e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return (${baseClassName})bind(bindingComponent, view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
10888b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
10894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
109143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
109243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
1093dea555cf42dc3583604699c8c018d22681f56166George Mount}
1094