LayoutBinderWriter.kt revision e4cd38824a6627b9fef229c549c636e35ad63b5f
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
171e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarfun Expr.toCode(full : Boolean = false) : KCode = CodeGenUtil.toCode(this, full)
172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
177de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagSet by Delegates.lazy { expr : Expr ->
178d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
181de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagSet by Delegates.lazy { expr : Expr ->
182d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getId())
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
1857b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarval Expr.shouldReadFlagSet by Delegates.versionedLazy { expr : Expr ->
186d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
189de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlags by Delegates.lazy { expr : Expr ->
190d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
191d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
194e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mountval LayoutBinder.requiredComponent by Delegates.lazy { layoutBinder: LayoutBinder ->
195e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    val required = layoutBinder.
196e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            getBindingTargets().
197e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            flatMap { it.getBindings() }.
198e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            firstOrNull { it.getBindingAdapterInstanceClass() != null }
199e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    required?.getBindingAdapterInstanceClass()
200e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount}
201e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
217d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (getLocalName() == null) binaryCode(bucketIndex)
218d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
219d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
220d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
221d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
222d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
223d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun longToBinary(l : Long) =
224d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        "0b${java.lang.Long.toBinaryString(l)}L"
225d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
226d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
228d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
23896e1c821dd446d1ed78f8ae61131550588f60a24George Mountfun indexFromTag(tag : String) : kotlin.Int {
23996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    val startIndex : kotlin.Int
2407ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    if (tag.startsWith("binding_")) {
2417ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        startIndex = "binding_".length();
24296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    } else {
24396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        startIndex = tag.lastIndexOf('_') + 1
24496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
24596e1c821dd446d1ed78f8ae61131550588f60a24George Mount    return Integer.parseInt(tag.substring(startIndex))
24696e1c821dd446d1ed78f8ae61131550588f60a24George Mount}
24796e1c821dd446d1ed78f8ae61131550588f60a24George Mount
24843596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
249d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
25034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
25143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
25243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
25343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
25443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
25543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
25643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
257d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
258d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
25943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
260dea555cf42dc3583604699c8c018d22681f56166George Mount    val className = layoutBinder.getImplementationName()
261d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
262dea555cf42dc3583604699c8c018d22681f56166George Mount    val baseClassName = "${layoutBinder.getClassName()}"
263d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2647551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
2657551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
2667551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
2677551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
26843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
26943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
27043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
271d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
2735bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
2745bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
275d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public fun write(minSdk : kotlin.Int) : String  {
2775bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
27834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
2795bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
280a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
281a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
2825bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
283dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
284dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
285dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends ${baseClassName}"
286dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
287dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends android.databinding.ViewDataBinding"
288dea555cf42dc3583604699c8c018d22681f56166George Mount            }
289dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public class ${classDeclaration} {") {
2904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
2915bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
2925bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
29320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                tab(declareBoundValues())
294716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab(declareListeners())
29596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab(declareConstructor(minSdk))
2965bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
297447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab(declareHasPendingBindings())
2985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
2995bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
3005bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
3015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3034c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3045bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
305716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab(declareListenerImpls())
3065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
307dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
308dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
309dea555cf42dc3583604699c8c018d22681f56166George Mount                }
3105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3115bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3125bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3145bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3155bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
31634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
31796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getBindingTargets().filter{
318d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount            it.isUsed() && it.getTag() != null && !it.isBinder()
31934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
32096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        taggedViews.forEach {
32196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it, indexFromTag(it.getTag()))
32296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
32396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val indexStart = maxIndex() + 1
32496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getBindingTargets().filter{
32596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && !taggedViews.contains(it)
32696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }.withIndex().forEach {
32796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it.value, it.index + indexStart)
32834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
32934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
3304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
331239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        nl("private static final android.databinding.ViewDataBinding.IncludedLayouts sIncludes;")
3324c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
3334c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
3344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
3354c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
3364c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
33700da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
33896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val numBindings = layoutBinder.getBindingTargets().filter{ it.isUsed() }.count()
339239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                tab("sIncludes = new android.databinding.ViewDataBinding.IncludedLayouts(${numBindings});")
34096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
34196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder() }.forEach {
34296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val includeTag = it.getTag();
34396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val parent = layoutBinder.getBindingTargets().firstOrNull {
34496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        it.isUsed() && !it.isBinder() && includeTag.equals(it.getTag())
34596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (parent == null) {
34796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        throw IllegalStateException("Could not find parent of include file")
34896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    var list = includeMap.get(parent)
35096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (list == null) {
35196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        list = ArrayList<BindingTarget>()
35296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.put(parent, list)
35396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
35496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    list.add(it)
3554c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
35696e1c821dd446d1ed78f8ae61131550588f60a24George Mount
35796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                includeMap.keySet().forEach {
35896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val index = indices.get(it)
359239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                    tab("sIncludes.setIncludes(${index}, ") {
360239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab ("new String[] {${
361239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
362239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "\"${it.getIncludedLayout()}\""
363239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
364239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }},")
365239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab("new int[] {${
366239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
367239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "${indices.get(it)}"
368239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
369239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }},")
370239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab("new int[] {${
371239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        includeMap.get(it).map {
372239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                            "R.layout.${it.getIncludedLayout()}"
373239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
374239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }});")
37596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
37696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
37796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
37896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val viewsWithIds = layoutBinder.getBindingTargets().filter {
379d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount                it.isUsed() && !it.isBinder() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
38000da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
38196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (viewsWithIds.isEmpty()) {
3824c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
38300da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
3844c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
38596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                viewsWithIds.forEach {
38634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sViewsWithIds.put(${it.androidId}, ${indices.get(it)});")
3874c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
38800da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
3894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
3904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
3914c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
39296e1c821dd446d1ed78f8ae61131550588f60a24George Mount
39396e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun maxIndex() : kotlin.Int {
39496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val maxIndex = indices.values().max()
39596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (maxIndex == null) {
39696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return -1
39796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
39896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return maxIndex
39996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
40096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
40196e1c821dd446d1ed78f8ae61131550588f60a24George Mount
40296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun declareConstructor(minSdk : kotlin.Int) = kcode("") {
40396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val bindingCount = maxIndex() + 1
40496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val parameterType : String
40596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val superParam : String
40696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (layoutBinder.isMerge()) {
40796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View[]"
40896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root[0]"
40996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
41096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View"
41196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root"
41296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
41396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val rootTagsSupported = minSdk >= 14
414dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
415dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
416e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public ${className}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root) {") {
417e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("this(bindingComponent, ${superParam}, mapBindings(bindingComponent, root, ${bindingCount}, sIncludes, sViewsWithIds));")
418dea555cf42dc3583604699c8c018d22681f56166George Mount            }
419dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
420e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("private ${className}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root, Object[] bindings) {") {
421e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, ${superParam}, ${model.getObservables().size()}") {
42296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    layoutBinder.getSortedTargets().filter { it.getId() != null }.forEach {
423dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
42434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
425dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
42634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
42734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
428dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
429e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public ${baseClassName}(android.databinding.DataBindingComponent bindingComponent, ${parameterType} root) {") {
430e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, ${superParam}, ${model.getObservables().size()});")
431e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("final Object[] bindings = mapBindings(bindingComponent, root, ${bindingCount}, sIncludes, sViewsWithIds);")
432dea555cf42dc3583604699c8c018d22681f56166George Mount            }
433dea555cf42dc3583604699c8c018d22681f56166George Mount        }
434e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        if (layoutBinder.requiredComponent != null) {
435e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("ensureBindingComponentIsNotNull(${layoutBinder.requiredComponent}.class);")
436e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
43796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getSortedTargets().filter{it.isUsed()}
438dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
439dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!layoutBinder.hasVariations() || it.getId() == null) {
440dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
441dea555cf42dc3583604699c8c018d22681f56166George Mount            }
442d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount            if (!it.isBinder()) {
443de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                if (it.getResolvedType() != null && it.getResolvedType().extendsViewStub()) {
444de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
445de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
44696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (it.supportsTag() && it.getTag() != null &&
4477ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        (rootTagsSupported || it.getTag().startsWith("binding_"))) {
448dea555cf42dc3583604699c8c018d22681f56166George Mount                    val originalTag = it.getOriginalTag();
449dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
450dea555cf42dc3583604699c8c018d22681f56166George Mount                    if (originalTag != null) {
451dea555cf42dc3583604699c8c018d22681f56166George Mount                        tagValue = "\"${originalTag}\""
452dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
453dea555cf42dc3583604699c8c018d22681f56166George Mount                            var packageName = layoutBinder.getModulePackage()
454dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
455dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
45600da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
457dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
458dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
459dea555cf42dc3583604699c8c018d22681f56166George Mount                            tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
46000da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
46100da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
462dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab("this.${it.fieldName}.setTag(${tagValue});")
4637551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
464d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
465d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4664d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount        tab("setRootTag(root);")
467dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
4680fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
469d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
470d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
471dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
472dea555cf42dc3583604699c8c018d22681f56166George Mount        if (!target.isUsed()) {
473dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
474dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
47596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val index = indices.get(target)
476dea555cf42dc3583604699c8c018d22681f56166George Mount            if (index == null) {
47796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                throw IllegalStateException("Unknown binding target")
478dea555cf42dc3583604699c8c018d22681f56166George Mount            }
47996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val variableName = "bindings[${index}]"
480dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
481dea555cf42dc3583604699c8c018d22681f56166George Mount        }
482dea555cf42dc3583604699c8c018d22681f56166George Mount    }
483dea555cf42dc3583604699c8c018d22681f56166George Mount
484d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
4857551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
4867551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
487019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            val fs = FlagSet(layoutBinder.getModel().getInvalidateAnyBitSet(),
488019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    layoutBinder.getModel().getFlagBucketCount());
4891c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
4901c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
4911c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
4921c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
4931c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
4945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
4957551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
4967551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
4972f64c44e4fa296cf658ca986c095eab62f82a31dYigit Boyar            tab("requestRebind();");
498d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4990fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
500d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
501d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
502447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    fun declareHasPendingBindings()  = kcode("") {
503447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("@Override")
504447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("public boolean hasPendingBindings() {") {
505447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            if (mDirtyFlags.buckets.size() > 0) {
506447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("synchronized(this) {") {
507447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    val flagCheck = 0.rangeTo(mDirtyFlags.buckets.size() - 1).map {
508447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                            "${mDirtyFlags.localValue(it)} != 0"
509447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }.joinToString(" || ")
510447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("if (${flagCheck}) {") {
511447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                        tab("return true;")
512447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }
513447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("}")
514447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
515447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
516447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
517447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            includedBinders.filter{it.isUsed()}.forEach { binder ->
518447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("if (${binder.fieldName}.hasPendingBindings()) {") {
519447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("return true;")
520447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
521447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
522447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
523447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            tab("return false;")
524447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        }
525447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("}")
526447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    }
527447971abca811b11b8c1d8e7bfaa294856d03c16George Mount
528d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
5290fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
530d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
5315bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
53243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab ("case ${it.getName().br()} :") {
533d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);")
534d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
535d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
536d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
537d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
538d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
539d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
540d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5410fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
542d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
543d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
544d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareLog() = kcode("") {
5450fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("private void log(String msg, long i) {") {
546d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""")
5470fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        }
5480fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
549d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
550d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
551d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
5525bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filterNot{it.isUsed()}.forEach {
553019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
5545bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
5555bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5565bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5575bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
5585bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
5595bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("return ${it.getDefaultValue()};")
5605bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5615bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5625bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
5635bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
56418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount            if (it.getUserDefinedType() != null) {
565019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
56618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
567019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                        tab("updateRegistration(${it.getId()}, ${it.readableName});");
56818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
569019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.readableName};")
57018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
57118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
5721c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("synchronized(this) {") {
5731c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
5741c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
5751c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        }
5761c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    } tab ("}")
57718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
578d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
57918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
58018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
58118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
58218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
58418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
586d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
59034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
59134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
5924c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
593d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
594d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
596d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
597d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
598d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
599d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
600d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
601d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
60234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
60334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
604d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
605d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
606019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableName}, int fieldId) {") {
607d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
608d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
609c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount                    accessedFields.filter { it.hasBindableAnnotations() }
610d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
611d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
61243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
613d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
6141c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    tab("synchronized(this) {") {
6151c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
6161c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                            tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
6171c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        }
6181c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    } tab("}")
619d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
620d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
621d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
622d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
62343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
624d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
6251c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        tab("synchronized(this) {") {
6261c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            mDirtyFlags.mapOr(flagSet) { suffix, index ->
6271c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
6281c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            }
6291c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        } tab("}")
630d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
632d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
633d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
634d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
635d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
636d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
63734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
63834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
639d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
640d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
641d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
642d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
643dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
64496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getSortedTargets().filter {it.isUsed() && (oneLayout || it.getId() == null)}.forEach {
645dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
646dea555cf42dc3583604699c8c018d22681f56166George Mount            if (oneLayout && it.getId() != null) {
647dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
648dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
649dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
650dea555cf42dc3583604699c8c018d22681f56166George Mount            }
651dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${access} final ${it.interfaceType} ${it.fieldName};")
652d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
653d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
654d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
655d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
6565bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
6570fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
658d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
659d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
660d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
66120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    fun declareBoundValues() = kcode("// values") {
66220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        layoutBinder.getSortedTargets().filter { it.isUsed() }
66320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .flatMap { it.getBindings() }
66420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .filter { it.requiresOldValue() }
66520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .flatMap{ it.getComponentExpressions().toArrayList() }
66620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .groupBy { it }
66720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .forEach {
66820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    val expr = it.getKey()
66920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    nl("private ${expr.getResolvedType().toJavaCode()} ${expr.oldValueName};")
67020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                }
67120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    }
67220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
673716ba89e7f459f49ea85070d4710c1d79d715298George Mount    fun declareListeners() = kcode("// listeners") {
674716ba89e7f459f49ea85070d4710c1d79d715298George Mount        model.getExprMap().values().filter {
675716ba89e7f459f49ea85070d4710c1d79d715298George Mount            it is FieldAccessExpr && it.isListener()
676716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }.groupBy { it }.forEach {
677716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val expr = it.key as FieldAccessExpr
678716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("private ${expr.listenerClassName} ${expr.fieldName};")
679716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
680716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
681716ba89e7f459f49ea85070d4710c1d79d715298George Mount
682d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
683d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
684de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
6850fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
686d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
687d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = ${longToBinary(value)};")
688d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
689d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
690d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
691d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
692d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
693d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
694d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
695d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
696d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
697d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
698d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
699d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
700d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
701d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7024c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
7030fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
704e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        nl("protected void executeBindings() {") {
705d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
706d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
707d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
7081c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = 0;")
709d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
7101c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
7111c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..mDirtyFlags.buckets.size() - 1)) {
7121c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
7131c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = 0;")
7141c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
7151c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
7164a81aabc49f6c881d960cd541adda7de9625277aYigit Boyar            model.getPendingExpressions().filterNot {!it.canBeEvaluatedToAVariable() || (it.isVariable() && !it.isUsed())}.forEach {
7174a81aabc49f6c881d960cd541adda7de9625277aYigit Boyar                tab("${it.getResolvedType().toJavaCode()} ${it.executePendingLocalName} = ${if(it.isVariable()) it.fieldName else it.getDefaultValue()};")
718d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
719b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar            L.d("writing executePendingBindings for %s", className)
720d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
72174f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
722b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                L.d("batch: %s", batch)
723d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val mJustRead = arrayListOf<Expr>()
724d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
7250fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    val readNow = batch.filter { it.shouldReadNow(mJustRead) }
726d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
727d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
728d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
729b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                    L.d("new read now. batch size: %d, readNow size: %d", batch.size(), readNow.size())
730d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
731d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    readNow.forEach {
7320fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        nl(readWithDependants(it, mJustRead, batch, tmpDirtyFlags))
733d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
734d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    batch.removeAll(mJustRead)
735d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7360fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
737d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } while(model.markBitsRead())
7387b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            // verify everything is read.
7397b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
7407b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            if (batch.isNotEmpty()) {
7417b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                L.e("could not generate code for %s. This might be caused by circular dependencies."
7427b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                        + "Please report on b.android.com", layoutBinder.getLayoutname())
7437b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            }
744d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
74596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
746d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
747d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .groupBy { it.getExpr() }
748d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .forEach {
749d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.key.dirtyFlagSet
750d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
751d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
752d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }.joinToString(" || ")
753d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }) {") {
754d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
75597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                tab("// api target ${binding.getMinApi()}")
75634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val fieldName : String
757d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount                                if (binding.getTarget().getViewClass().
75834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                        equals(binding.getTarget().getInterfaceType())) {
75934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "this.${binding.getTarget().fieldName}"
76034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
76134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "((${binding.getTarget().getViewClass()}) this.${binding.getTarget().fieldName})"
76234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
763e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                                val bindingCode = binding.toJavaCode(fieldName, "this.mBindingComponent")
76497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                if (binding.getMinApi() > 1) {
7654c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                                    tab("if(getBuildSdkInt() >= ${binding.getMinApi()}) {") {
76697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                        tab("$bindingCode;")
76797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    }
76897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("}")
76997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                } else {
77097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("$bindingCode;")
77197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                }
772d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
77320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }
77420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        tab("}")
77520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    }
77620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
77720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
77820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .flatMap { it.getBindings() }
77920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .filter { it.requiresOldValue() }
78020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .groupBy { it.getExpr() }
78120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .forEach {
78220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        val flagSet = it.key.dirtyFlagSet
78320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        tab("if (${tmpDirtyFlags.mapOr(flagSet) { suffix, index ->
78420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
78520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }.joinToString(" || ")
78620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }) {") {
78720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                            it.value.first().getComponentExpressions().forEach { expr ->
78820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                                tab("this.${expr.oldValueName} = ${expr.toCode(false).generate()};")
78920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                            }
790d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
791d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("}")
792d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
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
808d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    fun readWithDependants(expr : Expr, mJustRead : MutableList<Expr>, batch : MutableList<Expr>,
809d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tmpDirtyFlags : FlagSet, inheritedFlags : FlagSet? = null) : KCode = kcode("") {
810d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mJustRead.add(expr)
811b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar        L.d("%s / readWithDependants %s", className, expr.getUniqueKey());
812d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val flagSet = expr.shouldReadFlagSet
813d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
814b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar        L.d("flag set:%s . inherited flags: %s. need another if: %s", flagSet, inheritedFlags, needsIfWrapper);
815d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
81643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
81743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.joinToString(" || ")
818d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        })"
819d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
820d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val readCode = kcode("") {
821e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar            if (expr.canBeEvaluatedToAVariable() && !expr.isVariable()) {
822d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // it is not a variable read it.
823d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("// read ${expr.getUniqueKey()}")
824d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // create an if case for all dependencies that might be null
825d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val nullables = expr.getDependencies().filter {
826e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount                    it.isMandatory() && it.getOther().getResolvedType().isNullable()
82774f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                }.map { it.getOther() }
828d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
829019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab ("if ( ${nullables.map { "${it.executePendingLocalName} != null" }.joinToString(" && ")}) {") {
830019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                        tab("${expr.executePendingLocalName}").app(" = ", expr.toCode(true)).app(";")
831d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
832d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("}")
833d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                } else {
834019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("${expr.executePendingLocalName}").app(" = ", expr.toCode(true)).app(";")
835d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8367920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                if (expr.isObservable()) {
837019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("updateRegistration(${expr.getId()}, ${expr.executePendingLocalName});")
838d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8390fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            }
840d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
8410fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            // if I am the condition for an expression, set its flag
8420fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            val conditionals = expr.getDependants().filter { !it.isConditional()
8430fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    && it.getDependant() is TernaryExpr && (it.getDependant() as TernaryExpr).getPred() == expr }
8440fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    .map { it.getDependant() }
8450fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            if (conditionals.isNotEmpty()) {
8460fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// setting conditional flags")
847019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                tab("if (${expr.executePendingLocalName}) {") {
8480fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8490fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(true)
8500fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8510fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
852d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
853d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
854d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8550fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("} else {") {
8560fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8570fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(false)
8580fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8590fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
8600fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
8610fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
8620fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                } tab("}")
863d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
8640fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
865d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val chosen = expr.getDependants().filter {
866d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val dependant = it.getDependant()
867d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                batch.contains(dependant) &&
868d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadFlagSet.andNot(flagSet).isEmpty() &&
869d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadNow(mJustRead)
870d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
871d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (chosen.isNotEmpty()) {
872d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
873d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                chosen.forEach {
874d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                    nl(readWithDependants(it.getDependant(), mJustRead, batch, tmpDirtyFlags, nextInheritedFlags))
875d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
876d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
877d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
878d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (needsIfWrapper) {
879d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab(ifClause) {
880d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" {")
881d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                nl(readCode)
882d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
883d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab("}")
884d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
885d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            nl(readCode)
886d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
887d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
888716ba89e7f459f49ea85070d4710c1d79d715298George Mount
889716ba89e7f459f49ea85070d4710c1d79d715298George Mount    fun declareListenerImpls() = kcode("// Listener Stub Implementations") {
890716ba89e7f459f49ea85070d4710c1d79d715298George Mount        model.getExprMap().values().filter {
891716ba89e7f459f49ea85070d4710c1d79d715298George Mount            it.isUsed() && it is FieldAccessExpr && it.isListener()
892716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }.groupBy { it }.forEach {
893716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val expr = it.key as FieldAccessExpr
894716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val listeners = expr.getListenerTypes()
895716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val extends = listeners.firstOrNull{ !it.isInterface() }
896716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val extendsImplements = StringBuilder()
897716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (extends != null) {
898716ba89e7f459f49ea85070d4710c1d79d715298George Mount                extendsImplements.append("extends ${extends.toJavaCode()} ");
899716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
900716ba89e7f459f49ea85070d4710c1d79d715298George Mount            val implements = expr.getListenerTypes().filter{ it.isInterface() }.map {
901716ba89e7f459f49ea85070d4710c1d79d715298George Mount                it.toJavaCode()
902716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }.joinToString(", ")
903716ba89e7f459f49ea85070d4710c1d79d715298George Mount            if (!implements.isEmpty()) {
904716ba89e7f459f49ea85070d4710c1d79d715298George Mount                extendsImplements.append("implements ${implements}")
905716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
906716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("public static class ${expr.listenerClassName} ${extendsImplements} {") {
907716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab("public ${expr.listenerClassName}() {}")
908716ba89e7f459f49ea85070d4710c1d79d715298George Mount                if (expr.getChild().isDynamic()) {
909716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("private ${expr.getChild().getResolvedType().toJavaCode()} value;")
910716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("public ${expr.listenerClassName} setValue(${expr.getChild().getResolvedType().toJavaCode()} value) {") {
911716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("this.value = value;")
912716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("return value == null ? null : this;")
913716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }
914716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("}")
915716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
916716ba89e7f459f49ea85070d4710c1d79d715298George Mount                val signatures = HashSet<String>()
917716ba89e7f459f49ea85070d4710c1d79d715298George Mount                expr.getListenerMethods().withIndex().forEach {
918716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val listener = it.value
919716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val calledMethod = expr.getCalledMethods().get(it.index)
920716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val parameterTypes = listener.getParameterTypes()
921716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val returnType = listener.getReturnType(parameterTypes.toArrayList())
922716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    val signature = "public ${returnType} ${listener.getName()}(${
923716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    parameterTypes.withIndex().map {
924716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        "${it.value.toJavaCode()} arg${it.index}"
925716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }.joinToString(", ")
926716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }) {"
927716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    if (!signatures.contains(signature)) {
928716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        signatures.add(signature)
929716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("@Override")
930716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab(signature) {
931716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            val obj : String
932716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            if (expr.getChild().isDynamic()) {
933716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                obj = "this.value"
934716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            } else {
935716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                obj = expr.getChild().toCode(false).generate();
936716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            }
937716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            val returnStr : String
938716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            if (!returnType.isVoid()) {
939716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                returnStr = "return "
940716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            } else {
941716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                returnStr = ""
942716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            }
943716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            val args = parameterTypes.withIndex().map {
944716ba89e7f459f49ea85070d4710c1d79d715298George Mount                                "arg${it.index}"
945716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            }.joinToString(", ")
946716ba89e7f459f49ea85070d4710c1d79d715298George Mount                            tab("${returnStr}${obj}.${calledMethod.getName()}(${args});")
947716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        }
948716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("}")
949716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }
950716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
951716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
952716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("}")
953716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
954716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
95543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
956dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
957081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
958e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
959e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
960e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        nl("}")
961e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
962e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("return android.databinding.DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot, bindingComponent);")
963081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        }
964081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("}")
96596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (!layoutBinder.isMerge()) {
966081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount            nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
967e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
968e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
969e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("}")
970e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
971e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return bind(inflater.inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false), bindingComponent);")
97296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
97396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
97496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} bind(android.view.View view) {") {
975e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
976e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
977e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("}")
978e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("public static ${baseClassName} bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
97996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("if (!\"${layoutBinder.getTag()}_0\".equals(view.getTag())) {") {
980f80b08430f11515ff944f89006799f21545602b9George Mount                    tab("throw new RuntimeException(\"view tag isn't correct on view:\" + view.getTag());")
98196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
98296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("}")
983e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return new ${baseClassName}(bindingComponent, view);")
98496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
98596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
986dea555cf42dc3583604699c8c018d22681f56166George Mount        }
987dea555cf42dc3583604699c8c018d22681f56166George Mount    }
988dea555cf42dc3583604699c8c018d22681f56166George Mount
9898b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    /**
9908b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar     * When called for a library compilation, we do not generate real implementations
9918b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar     */
9928b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    public fun writeBaseClass(forLibrary : Boolean) : String =
99343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
994fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
995fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
996fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
9974c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
99896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
999de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("public final ${it.interfaceType} ${it.fieldName};")
100034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
100134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
1002e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("protected ${baseClassName}(android.databinding.DataBindingComponent bindingComponent, android.view.View root_, int localFieldCount") {
100396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
1004019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab(", ${it.interfaceType} ${it.constructorParamName}")
100534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
100634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
100734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
1008e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, root_, localFieldCount);")
100996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
1010019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.constructorParamName};")
101134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
10124c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10134c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
10144c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
101543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
101618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
1017895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
1018019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("public abstract void ${it.setterName}(${type} ${it.readableName});")
101918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
102043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
10219bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
1022e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
1023e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1024e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1025e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
1026e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
1027e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1028e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1029e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
10308b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10318b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10328b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1033e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
10348b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
103543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
10364c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
1037e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
10388b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10398b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10408b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1041e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot, bindingComponent);")
10428b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
10434c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10444c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
1045e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
1046e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                if (forLibrary) {
1047e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return null;")
1048e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                } else {
1049e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false, bindingComponent);")
1050e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                }
1051e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1052e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
1053e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("public static ${baseClassName} bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
10548b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10558b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10568b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1057e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return (${baseClassName})bind(bindingComponent, view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
10588b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
10594c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10604c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
106143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
106243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
1063dea555cf42dc3583604699c8c018d22681f56166George Mount}
1064