LayoutBinderWriter.kt revision a0820baa03e731f274ef55c5541e9fc101bbaddb
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
22716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.expr.TernaryExpr
237b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.androidId
247b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.br
257b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.joinToCamelCaseAsVar
26716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.ext.lazy
27716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.ext.versionedLazy
28fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer
297b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.util.L
3096e1c821dd446d1ed78f8ae61131550588f60a24George Mountimport java.util.ArrayList
31716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport java.util.Arrays
32716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport java.util.BitSet
3334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.HashMap
34716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport java.util.HashSet
35716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport kotlin.properties.Delegates
3643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
37fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]".toRegex()).map{ it.trim() }.joinToCamelCaseAsVar()
38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
39019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarenum class Scope {
40fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    FIELD,
41fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    METHOD,
42fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    FLAG,
43fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    EXECUTE_PENDING_METHOD,
44019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    CONSTRUCTOR_PARAM
45019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar}
46019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
48019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val usedFieldNames = hashMapOf<Scope, MutableSet<String>>();
49fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    init {
50019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        Scope.values().forEach { usedFieldNames[it] = hashSetOf<String>() }
51019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    }
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val localizedFlags = arrayListOf<FlagSet>()
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun localizeFlag(set : FlagSet, name:String) : FlagSet {
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        localizedFlags.add(set)
56019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        val result = getUniqueName(name, Scope.FLAG)
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        set.setLocalName(result)
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return set
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
61019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    fun getUniqueName(base : String, scope : Scope) : String {
62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var candidate = base
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var i = 0
64019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        while (usedFieldNames[scope].contains(candidate)) {
65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            i ++
66d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            candidate = base + i
67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
68019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        usedFieldNames[scope].add(candidate)
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return candidate
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
73de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval ExprModel.ext by Delegates.lazy { target : ExprModel ->
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    ExprModelExt()
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
77019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarfun ExprModel.getUniqueFieldName(base : String) : String = ext.getUniqueName(base, Scope.FIELD)
78019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarfun ExprModel.getUniqueMethodName(base : String) : String = ext.getUniqueName(base, Scope.METHOD)
79019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarfun ExprModel.getUniqueFlagName(base : String) : String = ext.getUniqueName(base, Scope.FLAG)
80019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarfun ExprModel.getConstructorParamName(base : String) : String = ext.getUniqueName(base, Scope.CONSTRUCTOR_PARAM)
81d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
83d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
84019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// not necessarily unique. Uniqueness is solved per scope
85019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.readableName by Delegates.lazy { target: BindingTarget ->
8600da715547ee7d5d38a3b8576090ca427a94daa5George Mount    if (target.getId() == null) {
87019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        "boundView" + indexFromTag(target.getTag())
8800da715547ee7d5d38a3b8576090ca427a94daa5George Mount    } else {
89019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        target.getId().androidId().stripNonJava()
9000da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
927551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
93de38dd3ef0577d25b2d59863603abe5750d0c231George Mountfun BindingTarget.superConversion(variable : String) : String {
9496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    if (getResolvedType() != null && getResolvedType().extendsViewStub()) {
95de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "new android.databinding.ViewStubProxy((android.view.ViewStub) ${variable})"
96de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
97de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "(${interfaceType}) ${variable}"
98de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
99de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
100de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
101019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.fieldName : String by Delegates.lazy { target : BindingTarget ->
102019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val name : String
103019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    if (target.getId() == null) {
104019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        name = "m${target.readableName}"
105019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    } else {
106019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        name = target.readableName
10734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
108019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    target.getModel().getUniqueFieldName(name)
109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
111de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.androidId by Delegates.lazy { target : BindingTarget ->
112fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount    if (target.getId().startsWith("@android:id/")) {
113fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount        "android.R.id.${target.getId().androidId()}"
114fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount    } else {
115fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount        "R.id.${target.getId().androidId()}"
116fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount    }
117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
119de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.interfaceType by Delegates.lazy { target : BindingTarget ->
120de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    if (target.getResolvedType() != null && target.getResolvedType().extendsViewStub()) {
121de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        "android.databinding.ViewStubProxy"
122de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
123de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        target.getInterfaceType()
124de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
125de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
126de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
127019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.constructorParamName by Delegates.lazy { target : BindingTarget ->
128019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    target.getModel().getConstructorParamName(target.readableName)
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
131019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// not necessarily unique. Uniqueness is decided per scope
132de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableName by Delegates.lazy { expr : Expr ->
133019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val stripped = "${expr.getUniqueKey().stripNonJava()}"
134b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar    L.d("readableUniqueName for [%s] %s is %s", System.identityHashCode(expr), expr.getUniqueKey(), stripped)
135019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    stripped
136de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
137de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
138de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.fieldName by Delegates.lazy { expr : Expr ->
139019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueFieldName("m${expr.readableName.capitalize()}")
140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
142716ba89e7f459f49ea85070d4710c1d79d715298George Mountval Expr.listenerClassName by Delegates.lazy { expr : Expr ->
143716ba89e7f459f49ea85070d4710c1d79d715298George Mount    expr.getModel().getUniqueFieldName("${expr.readableName.capitalize()}Impl")
144716ba89e7f459f49ea85070d4710c1d79d715298George Mount}
145716ba89e7f459f49ea85070d4710c1d79d715298George Mount
14620c7182163d99575d382e065f5a5fe45ed6b87e2George Mountval Expr.oldValueName by Delegates.lazy { expr : Expr ->
14720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    expr.getModel().getUniqueFieldName("mOld${expr.readableName.capitalize()}")
14820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount}
14920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
150019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval Expr.executePendingLocalName by Delegates.lazy { expr : Expr ->
1514a81aabc49f6c881d960cd541adda7de9625277aYigit Boyar    "${expr.getModel().ext.getUniqueName(expr.readableName, Scope.EXECUTE_PENDING_METHOD)}"
152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
154de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.setterName by Delegates.lazy { expr : Expr ->
155019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("set${expr.readableName.capitalize()}")
156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
158de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.onChangeName by Delegates.lazy { expr : Expr ->
159019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("onChange${expr.readableName.capitalize()}")
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
162de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.getterName by Delegates.lazy { expr : Expr ->
163019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("get${expr.readableName.capitalize()}")
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
166de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagName by Delegates.lazy { expr : Expr ->
167019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueFlagName("sFlag${expr.readableName.capitalize()}")
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
171d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
175de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagSet by Delegates.lazy { expr : Expr ->
176d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
179de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagSet by Delegates.lazy { expr : Expr ->
180d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getId())
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
1837b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarval Expr.shouldReadFlagSet by Delegates.versionedLazy { expr : Expr ->
184d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
187de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlags by Delegates.lazy { expr : Expr ->
188d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
189d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
192e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mountval LayoutBinder.requiredComponent by Delegates.lazy { layoutBinder: LayoutBinder ->
193e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    val required = layoutBinder.
194e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            getBindingTargets().
195e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            flatMap { it.getBindings() }.
196e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            firstOrNull { it.getBindingAdapterInstanceClass() != null }
197e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    required?.getBindingAdapterInstanceClass()
198e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount}
199e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
215d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (getLocalName() == null) binaryCode(bucketIndex)
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
217d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
218d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
219d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
220d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
221d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun longToBinary(l : Long) =
222d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        "0b${java.lang.Long.toBinaryString(l)}L"
223d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
224d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
225d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
226d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
228d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
23696e1c821dd446d1ed78f8ae61131550588f60a24George Mountfun indexFromTag(tag : String) : kotlin.Int {
23796e1c821dd446d1ed78f8ae61131550588f60a24George Mount    val startIndex : kotlin.Int
2387ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    if (tag.startsWith("binding_")) {
2397ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        startIndex = "binding_".length();
24096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    } else {
24196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        startIndex = tag.lastIndexOf('_') + 1
24296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
24396e1c821dd446d1ed78f8ae61131550588f60a24George Mount    return Integer.parseInt(tag.substring(startIndex))
24496e1c821dd446d1ed78f8ae61131550588f60a24George Mount}
24596e1c821dd446d1ed78f8ae61131550588f60a24George Mount
24643596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
247d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
24834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
24943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
25043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
25143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
25243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
25343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
25443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
256d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
25743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
258dea555cf42dc3583604699c8c018d22681f56166George Mount    val className = layoutBinder.getImplementationName()
259d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
260dea555cf42dc3583604699c8c018d22681f56166George Mount    val baseClassName = "${layoutBinder.getClassName()}"
261d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2627551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
2637551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
2647551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
2657551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
26643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
26743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
26843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2705bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
2715bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
2725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
273d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public fun write(minSdk : kotlin.Int) : String  {
2755bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
27634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
2775bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
278a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
279a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
2805bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
281dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
282dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
283dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends ${baseClassName}"
284dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
285dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends android.databinding.ViewDataBinding"
286dea555cf42dc3583604699c8c018d22681f56166George Mount            }
287dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public class ${classDeclaration} {") {
2884c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
2895bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
2905bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
29120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                tab(declareBoundValues())
292716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab(declareListeners())
29396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab(declareConstructor(minSdk))
2945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
295447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab(declareHasPendingBindings())
2965bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
2975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
2985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
2995bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3005bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3014c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
303716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab(declareListenerImpls())
3045bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
305dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
306dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
307dea555cf42dc3583604699c8c018d22681f56166George Mount                }
3085bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3095bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3115bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3125bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
31434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
31596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getBindingTargets().filter{
316d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount            it.isUsed() && it.getTag() != null && !it.isBinder()
31734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
31896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        taggedViews.forEach {
31996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it, indexFromTag(it.getTag()))
32096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
32196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val indexStart = maxIndex() + 1
32296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getBindingTargets().filter{
32396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && !taggedViews.contains(it)
32496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }.withIndex().forEach {
32596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it.value, it.index + indexStart)
32634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
32734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
3284c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
329239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        nl("private static final android.databinding.ViewDataBinding.IncludedLayouts sIncludes;")
3304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
3314c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
3324c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
3334c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
3344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
33500da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
33696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val numBindings = layoutBinder.getBindingTargets().filter{ it.isUsed() }.count()
337239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                tab("sIncludes = new android.databinding.ViewDataBinding.IncludedLayouts(${numBindings});")
33896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
33996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder() }.forEach {
34096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val includeTag = it.getTag();
34196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val parent = layoutBinder.getBindingTargets().firstOrNull {
34296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        it.isUsed() && !it.isBinder() && includeTag.equals(it.getTag())
34396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (parent == null) {
34596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        throw IllegalStateException("Could not find parent of include file")
34696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    var list = includeMap.get(parent)
34896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (list == null) {
34996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        list = ArrayList<BindingTarget>()
35096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.put(parent, list)
35196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
35296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    list.add(it)
3534c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
35496e1c821dd446d1ed78f8ae61131550588f60a24George Mount
35596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                includeMap.keySet().forEach {
35696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val index = indices.get(it)
357239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                    tab("sIncludes.setIncludes(${index}, ") {
358239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab ("new String[] {${
359239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
360239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "\"${it.getIncludedLayout()}\""
361239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
362239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }},")
363239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab("new int[] {${
364239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
365239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "${indices.get(it)}"
366239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
367239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }},")
368239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab("new int[] {${
369239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
370239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "R.layout.${it.getIncludedLayout()}"
371239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
372239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }});")
37396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
37496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
37596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
37696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val viewsWithIds = layoutBinder.getBindingTargets().filter {
377d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount                it.isUsed() && !it.isBinder() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
37800da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
37996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (viewsWithIds.isEmpty()) {
3804c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
38100da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
3824c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
38396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                viewsWithIds.forEach {
38434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sViewsWithIds.put(${it.androidId}, ${indices.get(it)});")
3854c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
38600da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
3874c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
3884c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
3894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
39096e1c821dd446d1ed78f8ae61131550588f60a24George Mount
39196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun maxIndex() : kotlin.Int {
39296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val maxIndex = indices.values().max()
39396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (maxIndex == null) {
39496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return -1
39596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
39696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return maxIndex
39796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
39896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
39996e1c821dd446d1ed78f8ae61131550588f60a24George Mount
40096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun declareConstructor(minSdk : kotlin.Int) = kcode("") {
40196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val bindingCount = maxIndex() + 1
40296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val parameterType : String
40396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val superParam : String
40496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (layoutBinder.isMerge()) {
40596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View[]"
40696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root[0]"
40796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
40896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View"
40996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root"
41096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
41196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val rootTagsSupported = minSdk >= 14
412dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
413dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
414e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public ${className}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root) {") {
415e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("this(bindingComponent, ${superParam}, mapBindings(bindingComponent, root, ${bindingCount}, sIncludes, sViewsWithIds));")
416dea555cf42dc3583604699c8c018d22681f56166George Mount            }
417dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
418e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("private ${className}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root, Object[] bindings) {") {
419e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, ${superParam}, ${model.getObservables().size()}") {
42096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    layoutBinder.getSortedTargets().filter { it.getId() != null }.forEach {
421dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
42234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
423dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
42434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
42534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
426dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
427e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public ${baseClassName}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root) {") {
428e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, ${superParam}, ${model.getObservables().size()});")
429e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("final Object[] bindings = mapBindings(bindingComponent, root, ${bindingCount}, sIncludes, sViewsWithIds);")
430dea555cf42dc3583604699c8c018d22681f56166George Mount            }
431dea555cf42dc3583604699c8c018d22681f56166George Mount        }
432e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        if (layoutBinder.requiredComponent != null) {
433e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("ensureBindingComponentIsNotNull(${layoutBinder.requiredComponent}.class);")
434e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
43596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getSortedTargets().filter{it.isUsed()}
436dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
437dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!layoutBinder.hasVariations() || it.getId() == null) {
438dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
439dea555cf42dc3583604699c8c018d22681f56166George Mount            }
440d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount            if (!it.isBinder()) {
441de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                if (it.getResolvedType() != null && it.getResolvedType().extendsViewStub()) {
442de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
443de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
44496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (it.supportsTag() && it.getTag() != null &&
4457ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        (rootTagsSupported || it.getTag().startsWith("binding_"))) {
446dea555cf42dc3583604699c8c018d22681f56166George Mount                    val originalTag = it.getOriginalTag();
447dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
448dea555cf42dc3583604699c8c018d22681f56166George Mount                    if (originalTag != null) {
449dea555cf42dc3583604699c8c018d22681f56166George Mount                        tagValue = "\"${originalTag}\""
450dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
451dea555cf42dc3583604699c8c018d22681f56166George Mount                            var packageName = layoutBinder.getModulePackage()
452dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
453dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
45400da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
455dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
456dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
457dea555cf42dc3583604699c8c018d22681f56166George Mount                            tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
45800da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
45900da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
460dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab("this.${it.fieldName}.setTag(${tagValue});")
4617551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
462d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
463d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4644d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount        tab("setRootTag(root);")
465dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
4660fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
467d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
468d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
469dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
470dea555cf42dc3583604699c8c018d22681f56166George Mount        if (!target.isUsed()) {
471dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
472dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
47396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val index = indices.get(target)
474dea555cf42dc3583604699c8c018d22681f56166George Mount            if (index == null) {
47596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                throw IllegalStateException("Unknown binding target")
476dea555cf42dc3583604699c8c018d22681f56166George Mount            }
47796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val variableName = "bindings[${index}]"
478dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
479dea555cf42dc3583604699c8c018d22681f56166George Mount        }
480dea555cf42dc3583604699c8c018d22681f56166George Mount    }
481dea555cf42dc3583604699c8c018d22681f56166George Mount
482d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
4837551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
4847551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
485019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            val fs = FlagSet(layoutBinder.getModel().getInvalidateAnyBitSet(),
486019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    layoutBinder.getModel().getFlagBucketCount());
4871c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
4881c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
4891c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
4901c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
4911c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
4925bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
4937551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
4947551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
4952f64c44e4fa296cf658ca986c095eab62f82a31dYigit Boyar            tab("requestRebind();");
496d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4970fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
498d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
499d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
500447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    fun declareHasPendingBindings()  = kcode("") {
501447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("@Override")
502447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("public boolean hasPendingBindings() {") {
503447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            if (mDirtyFlags.buckets.size() > 0) {
504447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("synchronized(this) {") {
505447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    val flagCheck = 0.rangeTo(mDirtyFlags.buckets.size() - 1).map {
506447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                            "${mDirtyFlags.localValue(it)} != 0"
507447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }.joinToString(" || ")
508447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("if (${flagCheck}) {") {
509447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                        tab("return true;")
510447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }
511447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("}")
512447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
513447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
514447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
515447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            includedBinders.filter{it.isUsed()}.forEach { binder ->
516447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("if (${binder.fieldName}.hasPendingBindings()) {") {
517447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("return true;")
518447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
519447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
520447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
521447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            tab("return false;")
522447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        }
523447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("}")
524447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    }
525447971abca811b11b8c1d8e7bfaa294856d03c16George Mount
526d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
5270fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
528d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
5295bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
53043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab ("case ${it.getName().br()} :") {
531d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);")
532d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
533d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
534d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
535d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
536d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
537d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
538d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5390fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
540d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
541d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
542d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareLog() = kcode("") {
5430fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("private void log(String msg, long i) {") {
544d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""")
5450fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        }
5460fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
547d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
548d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
549d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
5505bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filterNot{it.isUsed()}.forEach {
551019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
5525bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
5535bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5545bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5555bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
5565bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
5575bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("return ${it.getDefaultValue()};")
5585bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5595bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5605bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
5615bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
56218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount            if (it.getUserDefinedType() != null) {
563019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
56418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
565019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                        tab("updateRegistration(${it.getId()}, ${it.readableName});");
56618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
567019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.readableName};")
56818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
56918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
5701c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("synchronized(this) {") {
5711c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
5721c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
5731c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        }
5741c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    } tab ("}")
57518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
576d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
57718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
57818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
57918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
58018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
58218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
584d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
586d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
58834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
58934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
5904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
591d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
592d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
593d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
594d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
596d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
597d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
598d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
599d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
60034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
60134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
602d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
603d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
604019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableName}, int fieldId) {") {
605d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
606d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
607c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount                    accessedFields.filter { it.hasBindableAnnotations() }
608d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
609d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
61043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
611d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
6121c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    tab("synchronized(this) {") {
6131c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
6141c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                            tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
6151c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        }
6161c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    } tab("}")
617d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
618d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
619d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
620d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
62143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
622d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
6231c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        tab("synchronized(this) {") {
6241c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            mDirtyFlags.mapOr(flagSet) { suffix, index ->
6251c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
6261c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            }
6271c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        } tab("}")
628d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
629d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
630d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
632d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
633d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
634d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
63534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
63634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
637d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
638d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
639d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
640d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
641dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
64296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getSortedTargets().filter {it.isUsed() && (oneLayout || it.getId() == null)}.forEach {
643dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
644dea555cf42dc3583604699c8c018d22681f56166George Mount            if (oneLayout && it.getId() != null) {
645dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
646dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
647dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
648dea555cf42dc3583604699c8c018d22681f56166George Mount            }
649dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${access} final ${it.interfaceType} ${it.fieldName};")
650d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
651d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
652d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
653d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
6545bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
6550fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
656d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
657d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
658d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
65920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    fun declareBoundValues() = kcode("// values") {
66020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        layoutBinder.getSortedTargets().filter { it.isUsed() }
66120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .flatMap { it.getBindings() }
66220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .filter { it.requiresOldValue() }
66320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .flatMap{ it.getComponentExpressions().toArrayList() }
66420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .groupBy { it }
66520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .forEach {
66620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    val expr = it.getKey()
66720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    nl("private ${expr.getResolvedType().toJavaCode()} ${expr.oldValueName};")
66820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                }
66920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    }
67020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
671716ba89e7f459f49ea85070d4710c1d79d715298George Mount    fun declareListeners() = kcode("// listeners") {
672716ba89e7f459f49ea85070d4710c1d79d715298George Mount        model.getExprMap().values().filter {
673716ba89e7f459f49ea85070d4710c1d79d715298George Mount            it is FieldAccessExpr && it.isListener()
674716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }.groupBy { it }.forEach {
675716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val expr = it.key as FieldAccessExpr
676716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("private ${expr.listenerClassName} ${expr.fieldName};")
677716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
678716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
679716ba89e7f459f49ea85070d4710c1d79d715298George Mount
680d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
681d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
682de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
6830fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
684d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
685d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = ${longToBinary(value)};")
686d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
687d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
688d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
689d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
690d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
691d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
692d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
693d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
694d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
695d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
696d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
697d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
698d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
699d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7004c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
7010fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
702e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        nl("protected void executeBindings() {") {
703d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
704d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
705d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
7061c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = 0;")
707d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
7081c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
7091c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..mDirtyFlags.buckets.size() - 1)) {
7101c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
7111c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = 0;")
7121c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
7131c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
714a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            model.getPendingExpressions().filterNot { !it.canBeEvaluatedToAVariable() || (it.isVariable() && !it.isUsed()) }.forEach {
715a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("${it.getResolvedType().toJavaCode()} ${it.executePendingLocalName} = ${if (it.isVariable()) it.fieldName else it.getDefaultValue()};")
716d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
717b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar            L.d("writing executePendingBindings for %s", className)
718d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
71974f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
720a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                val justRead = arrayListOf<Expr>()
721b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                L.d("batch: %s", batch)
722d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
723a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val readNow = batch.filter { it.shouldReadNow(justRead) }
724d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
725d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
726d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
727b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                    L.d("new read now. batch size: %d, readNow size: %d", batch.size(), readNow.size())
728a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    nl(readWithDependants(readNow, justRead, batch, tmpDirtyFlags))
729a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    batch.removeAll(justRead)
730d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7310fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
732a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } while (model.markBitsRead())
7337b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            // verify everything is read.
7347b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
7357b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            if (batch.isNotEmpty()) {
7367b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                L.e("could not generate code for %s. This might be caused by circular dependencies."
737e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount                        + "Please report on b.android.com. %d %s %s", layoutBinder.getLayoutname(),
738e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount                        batch.size(), batch.get(0), batch.get(0).toCode().generate())
7397b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            }
740d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
74196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
742d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
743a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    .groupBy {
744a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        "${tmpDirtyFlags.mapOr(it.getExpr().dirtyFlagSet) { suffix, index ->
745a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            "(${tmpDirtyFlags.localValue(index)} & ${it.getExpr().dirtyFlagSet.localValue(index)}) != 0"
746a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }.joinToString(" || ") }"
747a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }.forEach {
748a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("if (${it.key}) {") {
749a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    it.value.groupBy { Math.max(1, it.getMinApi()) }.forEach {
750a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val setterValues = kcode("") {
751d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
752a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                val fieldName: String
753d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount                                if (binding.getTarget().getViewClass().
75434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                        equals(binding.getTarget().getInterfaceType())) {
75534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "this.${binding.getTarget().fieldName}"
75634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
75734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "((${binding.getTarget().getViewClass()}) this.${binding.getTarget().fieldName})"
75834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
759a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                tab(binding.toJavaCode(fieldName, "this.mBindingComponent")).app(";")
760a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
761a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
762a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        tab("// api target ${it.key}")
763a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (it.key > 1) {
764a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("if(getBuildSdkInt() >= ${it.key}) {") {
765a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                app("", setterValues)
766d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
767a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("}")
768a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        } else {
769a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            app("", setterValues)
77020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }
77120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    }
772a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
773a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
774a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }
775a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
77620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
77720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
77820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .flatMap { it.getBindings() }
77920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .filter { it.requiresOldValue() }
780a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    .groupBy {"${tmpDirtyFlags.mapOr(it.getExpr().dirtyFlagSet) { suffix, index ->
781a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        "(${tmpDirtyFlags.localValue(index)} & ${it.getExpr().dirtyFlagSet.localValue(index)}) != 0"
782a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }.joinToString(" || ")
783a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }"}.forEach {
784a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("if (${it.key}) {") {
785a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    it.value.groupBy { it.getExpr() }.map { it.value.first() }.forEach {
786a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        it.getComponentExpressions().forEach { expr ->
787a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("this.${expr.oldValueName} = ${expr.toCode().generate()};")
788d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
789d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
790a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
791a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
792a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }
7935bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
7944c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
7957551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
79696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{
797de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                it.isUsed() && it.getResolvedType() != null && it.getResolvedType().extendsViewStub()
798de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }.forEach {
799de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("if (${it.fieldName}.getBinding() != null) {") {
800de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("${it.fieldName}.getBinding().executePendingBindings();")
801de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
802de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("}")
803de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
804d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
8050fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
806d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
807d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
808a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    fun readWithDependants(expressionList: List<Expr>, justRead: MutableList<Expr>,
809a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            batch: MutableList<Expr>, tmpDirtyFlags: FlagSet,
810a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            inheritedFlags: FlagSet? = null) : KCode = kcode("") {
811a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount        expressionList.groupBy { it.shouldReadFlagSet }.forEach {
812a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val flagSet = it.key
813a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
814a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val expressions = it.value
815a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
816a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
817a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }.joinToString(" || ")
818a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            })"
819a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val readCode = kcode("") {
820a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                val dependants = ArrayList<Expr>()
821a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                expressions.groupBy { condition(it) }.forEach {
822a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val condition = it.key
823a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val assignedValues = it.value.filter {
824a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        it.canBeEvaluatedToAVariable() && !it.isVariable()
825d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
826a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    if (!assignedValues.isEmpty()) {
827a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val assignment = kcode("") {
828a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            assignedValues.forEach { expr: Expr ->
829a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                tab("// read ${expr.getUniqueKey()}")
830a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                tab("${expr.executePendingLocalName}").app(" = ", expr.toFullCode()).app(";")
831a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
832a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
833a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (condition != null) {
834a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("if (${condition}) {") {
835a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                app("", assignment)
836a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
837a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab ("}")
838a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        } else {
839a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            app("", assignment)
840d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
841d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
842a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    it.value.filter { it.isObservable() }.forEach { expr: Expr ->
843a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        tab("updateRegistration(${expr.getId()}, ${expr.executePendingLocalName});")
844a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }
845a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
846a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    it.value.forEach { expr: Expr ->
847a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        justRead.add(expr)
848a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        L.d("%s / readWithDependants %s", className, expr.getUniqueKey());
849a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        L.d("flag set:%s . inherited flags: %s. need another if: %s", flagSet, inheritedFlags, needsIfWrapper);
850a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
851a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        // if I am the condition for an expression, set its flag
852a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val conditionals = expr.getDependants().filter {
853a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            !it.isConditional() && it.getDependant() is TernaryExpr &&
854a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    (it.getDependant() as TernaryExpr).getPred() == expr
855a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }.map { it.getDependant() }
856a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (conditionals.isNotEmpty()) {
857a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("// setting conditional flags")
858a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("if (${expr.executePendingLocalName}) {") {
859a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                conditionals.forEach {
860a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    val set = it.getRequirementFlagSet(true)
861a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    mDirtyFlags.mapOr(set) { suffix, index ->
862a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                        tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
863a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    }
864a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                }
865a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
866a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("} else {") {
867a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                conditionals.forEach {
868a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    val set = it.getRequirementFlagSet(false)
869a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    mDirtyFlags.mapOr(set) { suffix, index ->
870a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                        tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
871a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    }
872a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                }
873a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
874a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("}")
875a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
876a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
877a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val chosen = expr.getDependants().filter {
878a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            val dependant = it.getDependant()
879a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            batch.contains(dependant) &&
880a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    dependant.shouldReadFlagSet.andNot(flagSet).isEmpty() &&
881a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    dependant.shouldReadNow(justRead)
882a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
883a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (chosen.isNotEmpty()) {
884a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            dependants.addAll(chosen.map { it.getDependant() })
8850fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
8860fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
887a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
888a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                if (dependants.isNotEmpty()) {
889a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
890a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    nl(readWithDependants(dependants, justRead, batch, tmpDirtyFlags, nextInheritedFlags))
891a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
892d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
8930fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
894a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            if (needsIfWrapper) {
895a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab(ifClause) {
896a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    app(" {")
897a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    app("", readCode)
898d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
899a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
900a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } else {
901a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                app("", readCode)
902d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
903d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
904a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    }
905a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
906a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    fun condition(expr : Expr) : String? {
907a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount        if (expr.canBeEvaluatedToAVariable() && !expr.isVariable()) {
908a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            // create an if case for all dependencies that might be null
909a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val nullables = expr.getDependencies().filter {
910a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                it.isMandatory() && it.getOther().getResolvedType().isNullable()
911a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }.map { it.getOther() }
912a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
913a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                return "${nullables.map { "${it.executePendingLocalName} != null" }.joinToString(" && ")}"
914a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } else {
915a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                return null
916d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
917d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
918a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            return null
919d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
920d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
921716ba89e7f459f49ea85070d4710c1d79d715298George Mount
922716ba89e7f459f49ea85070d4710c1d79d715298George Mount    fun declareListenerImpls() = kcode("// Listener Stub Implementations") {
923716ba89e7f459f49ea85070d4710c1d79d715298George Mount        model.getExprMap().values().filter {
924716ba89e7f459f49ea85070d4710c1d79d715298George Mount            it.isUsed() && it is FieldAccessExpr && it.isListener()
925716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }.groupBy { it }.forEach {
926716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val expr = it.key as FieldAccessExpr
927716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val listeners = expr.getListenerTypes()
928716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val extends = listeners.firstOrNull{ !it.isInterface() }
929716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val extendsImplements = StringBuilder()
930716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (extends != null) {
931716ba89e7f459f49ea85070d4710c1d79d715298George Mount                extendsImplements.append("extends ${extends.toJavaCode()} ");
932716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
933716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val implements = expr.getListenerTypes().filter{ it.isInterface() }.map {
934716ba89e7f459f49ea85070d4710c1d79d715298George Mount                it.toJavaCode()
935716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }.joinToString(", ")
936716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (!implements.isEmpty()) {
937716ba89e7f459f49ea85070d4710c1d79d715298George Mount                extendsImplements.append("implements ${implements}")
938716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
939716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("public static class ${expr.listenerClassName} ${extendsImplements} {") {
940716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab("public ${expr.listenerClassName}() {}")
941716ba89e7f459f49ea85070d4710c1d79d715298George Mount                if (expr.getChild().isDynamic()) {
942716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("private ${expr.getChild().getResolvedType().toJavaCode()} value;")
943716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("public ${expr.listenerClassName} setValue(${expr.getChild().getResolvedType().toJavaCode()} value) {") {
944716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("this.value = value;")
945716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("return value == null ? null : this;")
946716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }
947716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("}")
948716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
949716ba89e7f459f49ea85070d4710c1d79d715298George Mount                val signatures = HashSet<String>()
950716ba89e7f459f49ea85070d4710c1d79d715298George Mount                expr.getListenerMethods().withIndex().forEach {
951716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val listener = it.value
952716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val calledMethod = expr.getCalledMethods().get(it.index)
953716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val parameterTypes = listener.getParameterTypes()
954716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val returnType = listener.getReturnType(parameterTypes.toArrayList())
955716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val signature = "public ${returnType} ${listener.getName()}(${
956716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    parameterTypes.withIndex().map {
957716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        "${it.value.toJavaCode()} arg${it.index}"
958716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }.joinToString(", ")
959716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }) {"
960716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    if (!signatures.contains(signature)) {
961716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        signatures.add(signature)
962716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("@Override")
963716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab(signature) {
964716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            val obj : String
965716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            if (expr.getChild().isDynamic()) {
966716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                obj = "this.value"
967716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            } else {
968e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount                                obj = expr.getChild().toCode().generate();
969716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            }
970716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            val returnStr : String
971716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            if (!returnType.isVoid()) {
972716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                returnStr = "return "
973716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            } else {
974716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                returnStr = ""
975716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            }
976716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            val args = parameterTypes.withIndex().map {
977716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                "arg${it.index}"
978716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            }.joinToString(", ")
979716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            tab("${returnStr}${obj}.${calledMethod.getName()}(${args});")
980716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        }
981716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("}")
982716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }
983716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
984716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
985716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("}")
986716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
987716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
98843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
989dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
990081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
991e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
992e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
993e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        nl("}")
994e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
995e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("return android.databinding.DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot, bindingComponent);")
996081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        }
997081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("}")
99896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (!layoutBinder.isMerge()) {
999081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount            nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
1000e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
1001e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1002e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("}")
1003e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
1004e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return bind(inflater.inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false), bindingComponent);")
100596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
100696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
100796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} bind(android.view.View view) {") {
1008e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
1009e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1010e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("}")
1011e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public static ${baseClassName} bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
101296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("if (!\"${layoutBinder.getTag()}_0\".equals(view.getTag())) {") {
1013f80b08430f11515ff944f89006799f21545602b9George Mount                    tab("throw new RuntimeException(\"view tag isn't correct on view:\" + view.getTag());")
101496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
101596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("}")
1016e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return new ${baseClassName}(bindingComponent, view);")
101796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
101896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
1019dea555cf42dc3583604699c8c018d22681f56166George Mount        }
1020dea555cf42dc3583604699c8c018d22681f56166George Mount    }
1021dea555cf42dc3583604699c8c018d22681f56166George Mount
10228b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    /**
10238b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar     * When called for a library compilation, we do not generate real implementations
10248b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar     */
10258b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    public fun writeBaseClass(forLibrary : Boolean) : String =
102643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
1027fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
1028fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
1029fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
10304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
103196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
1032de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("public final ${it.interfaceType} ${it.fieldName};")
103334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
103434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
1035e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("protected ${baseClassName}(android.databinding.DataBindingComponent bindingComponent, android.view.View root_, int localFieldCount") {
103696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
1037019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab(", ${it.interfaceType} ${it.constructorParamName}")
103834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
103934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
104034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
1041e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, root_, localFieldCount);")
104296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
1043019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.constructorParamName};")
104434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
10454c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10464c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
10474c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
104843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
104918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
1050895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
1051019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("public abstract void ${it.setterName}(${type} ${it.readableName});")
105218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
105343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
10549bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
1055e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
1056e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1057e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1058e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
1059e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
1060e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1061e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1062e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
10638b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10648b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10658b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1066e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
10678b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
106843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
10694c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
1070e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
10718b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10728b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10738b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1074e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot, bindingComponent);")
10758b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
10764c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10774c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
1078e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
1079e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                if (forLibrary) {
1080e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return null;")
1081e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                } else {
1082e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false, bindingComponent);")
1083e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                }
1084e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1085e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1086e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
10878b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10888b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10898b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1090e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return (${baseClassName})bind(bindingComponent, view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
10918b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
10924c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10934c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
109443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
109543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
1096dea555cf42dc3583604699c8c018d22681f56166George Mount}
1097