LayoutBinderWriter.kt revision 0b6d118e6eeb3bc100fc6a6e66016ab812cb2783
1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/*
2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project
3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License.
5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at
6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software
8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and
11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License.
12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */
13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
14fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.writer
15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
16e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.BindingTarget
17716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.LayoutBinder
18fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel
20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.FieldAccessExpr
21716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.expr.IdentifierExpr
22793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport android.databinding.tool.expr.ListenerExpr
23716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.expr.TernaryExpr
2409aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyarimport android.databinding.tool.expr.ResourceExpr
257b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.androidId
267b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.joinToCamelCaseAsVar
2759229481aec5a284d322a2ca80dff836485feb0cYigit Boyarimport android.databinding.tool.ext.lazyProp
28716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport android.databinding.tool.ext.versionedLazy
2959229481aec5a284d322a2ca80dff836485feb0cYigit Boyarimport android.databinding.tool.ext.br
3092a428505b9102bc0560d2d5be1768da097909c2George Mountimport android.databinding.tool.processing.ErrorMessages
31fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer
327b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.util.L
3396e1c821dd446d1ed78f8ae61131550588f60a24George Mountimport java.util.ArrayList
34716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport java.util.Arrays
35716ba89e7f459f49ea85070d4710c1d79d715298George Mountimport java.util.BitSet
3634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.HashMap
3743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
38fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]".toRegex()).map{ it.trim() }.joinToCamelCaseAsVar()
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
40019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarenum class Scope {
41fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    FIELD,
42fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    METHOD,
43fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    FLAG,
44fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    EXECUTE_PENDING_METHOD,
45019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    CONSTRUCTOR_PARAM
46019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar}
47019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
49019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val usedFieldNames = hashMapOf<Scope, MutableSet<String>>();
50fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    init {
5159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        Scope.values.forEach { usedFieldNames[it] = hashSetOf<String>() }
52019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    }
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val localizedFlags = arrayListOf<FlagSet>()
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun localizeFlag(set : FlagSet, name:String) : FlagSet {
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        localizedFlags.add(set)
57793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        val result = getUniqueName(name, Scope.FLAG, false)
5859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        set.localName = result
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return set
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
62793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    fun getUniqueName(base : String, scope : Scope, isPublic : kotlin.Boolean) : String {
63793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        var candidateBase = base
6459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        if (!isPublic && candidateBase.length > 20) {
65793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            candidateBase = candidateBase.substring(0, 20);
66793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        }
67793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        var candidate = candidateBase
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var i = 0
695d454e5f2397a3b160f081ce123b4ca7ff0fc356Yigit Boyar        while (usedFieldNames[scope]!!.contains(candidate)) {
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            i ++
71793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            candidate = candidateBase + i
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
735d454e5f2397a3b160f081ce123b4ca7ff0fc356Yigit Boyar        usedFieldNames[scope]!!.add(candidate)
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return candidate
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7859229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval ExprModel.ext by lazyProp { target : ExprModel ->
79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    ExprModelExt()
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
81d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
82793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountfun ExprModel.getUniqueFieldName(base : String, isPublic : kotlin.Boolean) : String = ext.getUniqueName(base, Scope.FIELD, isPublic)
83793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountfun ExprModel.getUniqueMethodName(base : String, isPublic : kotlin.Boolean) : String = ext.getUniqueName(base, Scope.METHOD, isPublic)
84793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountfun ExprModel.getConstructorParamName(base : String) : String = ext.getUniqueName(base, Scope.CONSTRUCTOR_PARAM, false)
85d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
8859229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.needsLocalField by lazyProp { expr : Expr ->
8959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    expr.canBeEvaluatedToAVariable() && !(expr.isVariable() && !expr.isUsed) && (expr.isDynamic || expr is ResourceExpr)
9009aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar}
9109aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar
9209aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar
93019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// not necessarily unique. Uniqueness is solved per scope
9459229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval BindingTarget.readableName by lazyProp { target: BindingTarget ->
9559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    if (target.id == null) {
9659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        "boundView" + indexFromTag(target.tag)
9700da715547ee7d5d38a3b8576090ca427a94daa5George Mount    } else {
9859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        target.id.androidId().stripNonJava()
9900da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
1017551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
102de38dd3ef0577d25b2d59863603abe5750d0c231George Mountfun BindingTarget.superConversion(variable : String) : String {
10359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    if (resolvedType != null && resolvedType.extendsViewStub()) {
10459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        return "new android.databinding.ViewStubProxy((android.view.ViewStub) $variable)"
105de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
10659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        return "($interfaceClass) $variable"
107de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
108de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
109de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
11059229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval BindingTarget.fieldName : String by lazyProp { target : BindingTarget ->
111019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val name : String
112793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount    val isPublic : kotlin.Boolean
11359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    if (target.id == null) {
114019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        name = "m${target.readableName}"
115793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        isPublic = false
116019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    } else {
117019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        name = target.readableName
118793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount        isPublic = true
11934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
12059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    target.model.getUniqueFieldName(name, isPublic)
121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
122d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
12359229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval BindingTarget.androidId by lazyProp { target : BindingTarget ->
12459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    if (target.id.startsWith("@android:id/")) {
12559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        "android.R.id.${target.id.androidId()}"
126fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount    } else {
12759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        "R.id.${target.id.androidId()}"
128fdfbbcd5ecf37d77a4b9ab1cefdebd68de71ca2bGeorge Mount    }
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
13159229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval BindingTarget.interfaceClass by lazyProp { target : BindingTarget ->
13259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    if (target.resolvedType != null && target.resolvedType.extendsViewStub()) {
133de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        "android.databinding.ViewStubProxy"
134de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
13559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        target.interfaceType
136de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
137de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
138de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
13959229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval BindingTarget.constructorParamName by lazyProp { target : BindingTarget ->
14059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    target.model.getConstructorParamName(target.readableName)
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
143019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// not necessarily unique. Uniqueness is decided per scope
14459229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.readableName by lazyProp { expr : Expr ->
14559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val stripped = "${expr.uniqueKey.stripNonJava()}"
14659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    L.d("readableUniqueName for [%s] %s is %s", System.identityHashCode(expr), expr.uniqueKey, stripped)
147019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    stripped
148de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
149de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
15059229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.fieldName by lazyProp { expr : Expr ->
15159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    expr.model.getUniqueFieldName("m${expr.readableName.capitalize()}", false)
152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
15459229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.listenerClassName by lazyProp { expr : Expr ->
15559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    expr.model.getUniqueFieldName("${expr.resolvedType.simpleName}Impl", false)
156716ba89e7f459f49ea85070d4710c1d79d715298George Mount}
157716ba89e7f459f49ea85070d4710c1d79d715298George Mount
15859229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.oldValueName by lazyProp { expr : Expr ->
15959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    expr.model.getUniqueFieldName("mOld${expr.readableName.capitalize()}", false)
16020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount}
16120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
16259229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.executePendingLocalName by lazyProp { expr : Expr ->
16359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    if(expr.needsLocalField) "${expr.model.ext.getUniqueName(expr.readableName, Scope.EXECUTE_PENDING_METHOD, false)}"
16409aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar    else expr.toCode().generate()
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
16759229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.setterName by lazyProp { expr : Expr ->
16859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    expr.model.getUniqueMethodName("set${expr.readableName.capitalize()}", true)
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
17159229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.onChangeName by lazyProp { expr : Expr ->
17259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    expr.model.getUniqueMethodName("onChange${expr.readableName.capitalize()}", false)
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
17559229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.getterName by lazyProp { expr : Expr ->
17659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    expr.model.getUniqueMethodName("get${expr.readableName.capitalize()}", true)
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
17959229481aec5a284d322a2ca80dff836485feb0cYigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
18159229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.dirtyFlagSet by lazyProp { expr : Expr ->
18259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    FlagSet(expr.invalidFlags, expr.model.flagBucketCount)
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
18559229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.invalidateFlagSet by lazyProp { expr : Expr ->
18659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    FlagSet(expr.id)
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
18959229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.shouldReadFlagSet by versionedLazy { expr : Expr ->
19059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    FlagSet(expr.shouldReadFlags, expr.model.flagBucketCount)
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
19359229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.shouldReadWithConditionalsFlagSet by versionedLazy { expr : Expr ->
19459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    FlagSet(expr.shouldReadFlagsWithConditionals, expr.model.flagBucketCount)
195eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar}
196eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar
19759229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval Expr.conditionalFlags by lazyProp { expr : Expr ->
198d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
199d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
20259229481aec5a284d322a2ca80dff836485feb0cYigit Boyarval LayoutBinder.requiredComponent by lazyProp { layoutBinder: LayoutBinder ->
203e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount    val required = layoutBinder.
20459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            bindingTargets.
20559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            flatMap { it.bindings }.
20659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            firstOrNull { it.bindingAdapterInstanceClass != null }
20759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    required?.bindingAdapterInstanceClass
208e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount}
209e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
217d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
218d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
219d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
22059229481aec5a284d322a2ca80dff836485feb0cYigit Boyarfun getWordSuffix(wordIndex : Int) : String {
22159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    return if(wordIndex == 0) "" else "_$wordIndex"
222d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
223d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
224d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
22559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        if (localName == null) binaryCode(bucketIndex)
22659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        else "$localName${getWordSuffix(bucketIndex)}"
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
228d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
229d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
230d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
23159229481aec5a284d322a2ca80dff836485feb0cYigit Boyarfun longToBinary(l : Long) = "0x${java.lang.Long.toHexString(l)}L"
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
23459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val min = Math.min(buckets.size, other.buckets.size)
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
238d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
239d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
240d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
241d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
242d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
243d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
244d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
24596e1c821dd446d1ed78f8ae61131550588f60a24George Mountfun indexFromTag(tag : String) : kotlin.Int {
24696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    val startIndex : kotlin.Int
2477ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    if (tag.startsWith("binding_")) {
24859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        startIndex = "binding_".length;
24996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    } else {
25096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        startIndex = tag.lastIndexOf('_') + 1
25196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
25296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    return Integer.parseInt(tag.substring(startIndex))
25396e1c821dd446d1ed78f8ae61131550588f60a24George Mount}
25496e1c821dd446d1ed78f8ae61131550588f60a24George Mount
25543596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
25659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val model = layoutBinder.model
25734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
25859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val mDirtyFlags by lazy {
25959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        val fs = FlagSet(BitSet(), model.flagBucketCount);
26043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
26159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        fs.isDynamic = true
26243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
26343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
264d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
26659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val className = layoutBinder.implementationName
267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
26859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val baseClassName = "${layoutBinder.className}"
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val includedBinders by lazy {
27159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        layoutBinder.bindingTargets.filter { it.isBinder }
2727551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
2737551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
27459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val variables by lazy {
27559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        model.exprMap.values.filterIsInstance(IdentifierExpr::class.java).filter { it.isVariable() }
27643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar    val usedVariables by lazy {
27959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        variables.filter {it.isUsed }
2805bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
281d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
28296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public fun write(minSdk : kotlin.Int) : String  {
2835bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
28434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
28559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        return kcode("package ${layoutBinder.`package`};") {
28659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("import ${layoutBinder.modulePackage}.R;")
28759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("import ${layoutBinder.modulePackage}.BR;")
2885bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
289dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
290dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
29159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                classDeclaration = "$className extends $baseClassName"
292dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
29359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                classDeclaration = "$className extends android.databinding.ViewDataBinding"
294dea555cf42dc3583604699c8c018d22681f56166George Mount            }
29559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public class $classDeclaration {") {
2964c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
2975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
2985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
29920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                tab(declareBoundValues())
300716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab(declareListeners())
30196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab(declareConstructor(minSdk))
3025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
303447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab(declareHasPendingBindings())
3045bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
3055bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
3065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3075bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3084c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3095bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
310716ba89e7f459f49ea85070d4710c1d79d715298George Mount                tab(declareListenerImpls())
3115bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
312dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
313dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
314dea555cf42dc3583604699c8c018d22681f56166George Mount                }
3155bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3165bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3175bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3185bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3195bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3205bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
32134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
32259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        val taggedViews = layoutBinder.bindingTargets.filter{
32359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            it.isUsed && it.tag != null && !it.isBinder
32434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
32596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        taggedViews.forEach {
32659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            indices.put(it, indexFromTag(it.tag))
32796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
32896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val indexStart = maxIndex() + 1
32959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        layoutBinder.bindingTargets.filter{
33059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            it.isUsed && !taggedViews.contains(it)
33196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }.withIndex().forEach {
33296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it.value, it.index + indexStart)
33334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
33434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
3354c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
336239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount        nl("private static final android.databinding.ViewDataBinding.IncludedLayouts sIncludes;")
3374c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
3384c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
33959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val hasBinders = layoutBinder.bindingTargets.firstOrNull{ it.isUsed && it.isBinder } != null
3404c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
3414c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
34200da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
34359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                val numBindings = layoutBinder.bindingTargets.filter{ it.isUsed }.count()
34459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("sIncludes = new android.databinding.ViewDataBinding.IncludedLayouts($numBindings);")
34596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
34659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                layoutBinder.bindingTargets.filter{ it.isUsed && it.isBinder }.forEach {
34759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    val includeTag = it.tag;
34859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    val parent = layoutBinder.bindingTargets.firstOrNull {
34959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        it.isUsed && !it.isBinder && includeTag.equals(it.tag)
35059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    } ?: throw IllegalStateException("Could not find parent of include file")
35159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    var list = includeMap[parent]
35296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (list == null) {
35396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        list = ArrayList<BindingTarget>()
35496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.put(parent, list)
35596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
35696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    list.add(it)
3574c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
35896e1c821dd446d1ed78f8ae61131550588f60a24George Mount
35959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                includeMap.keys.forEach {
36059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    val index = indices[it]
36159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("sIncludes.setIncludes($index, ") {
362239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab ("new String[] {${
36359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        includeMap[it]!!.map {
36459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            "\"${it.includedLayout}\""
365239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
366239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }},")
367239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab("new int[] {${
36859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        includeMap[it]!!.map {
36959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            "${indices[it]}"
370239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
371239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }},")
372239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        tab("new int[] {${
37359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        includeMap[it]!!.map {
37459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            "R.layout.${it.includedLayout}"
375239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }.joinToString(", ")
376239e15adad52d3a7d77852953a5dd7eee82f7f2cGeorge Mount                        }});")
37796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
37896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
37996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
38059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val viewsWithIds = layoutBinder.bindingTargets.filter {
38159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                it.isUsed && !it.isBinder && (!it.supportsTag() || (it.id != null && it.tag == null))
38200da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
38396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (viewsWithIds.isEmpty()) {
3844c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
38500da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
3864c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
38796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                viewsWithIds.forEach {
38859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("sViewsWithIds.put(${it.androidId}, ${indices[it]});")
3894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
39000da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
3914c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
3924c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
3934c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
39496e1c821dd446d1ed78f8ae61131550588f60a24George Mount
39596e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun maxIndex() : kotlin.Int {
39659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        val maxIndex = indices.values.max()
39796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (maxIndex == null) {
39896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return -1
39996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
40096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return maxIndex
40196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
40296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
40396e1c821dd446d1ed78f8ae61131550588f60a24George Mount
40496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun declareConstructor(minSdk : kotlin.Int) = kcode("") {
40596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val bindingCount = maxIndex() + 1
40696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val parameterType : String
40796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val superParam : String
40859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        if (layoutBinder.isMerge) {
40996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View[]"
41096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root[0]"
41196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
41296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View"
41396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root"
41496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
41596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val rootTagsSupported = minSdk >= 14
416dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
417dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
41859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public $className(android.databinding.DataBindingComponent bindingComponent, $parameterType root) {") {
41959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("this(bindingComponent, $superParam, mapBindings(bindingComponent, root, $bindingCount, sIncludes, sViewsWithIds));")
420dea555cf42dc3583604699c8c018d22681f56166George Mount            }
421dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
42259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("private $className(android.databinding.DataBindingComponent bindingComponent, $parameterType root, Object[] bindings) {") {
42359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("super(bindingComponent, $superParam, ${model.observables.size}") {
42459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    layoutBinder.sortedTargets.filter { it.id != null }.forEach {
425dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
42634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
427dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
42834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
42934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
430dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
43159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public $baseClassName(android.databinding.DataBindingComponent bindingComponent, $parameterType root) {") {
43259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("super(bindingComponent, $superParam, ${model.observables.size});")
43359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("final Object[] bindings = mapBindings(bindingComponent, root, $bindingCount, sIncludes, sViewsWithIds);")
434dea555cf42dc3583604699c8c018d22681f56166George Mount            }
435dea555cf42dc3583604699c8c018d22681f56166George Mount        }
436e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        if (layoutBinder.requiredComponent != null) {
437e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("ensureBindingComponentIsNotNull(${layoutBinder.requiredComponent}.class);")
438e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
43959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        val taggedViews = layoutBinder.sortedTargets.filter{it.isUsed }
440dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
44159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            if (!layoutBinder.hasVariations() || it.id == null) {
442dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
443dea555cf42dc3583604699c8c018d22681f56166George Mount            }
44459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            if (!it.isBinder) {
44559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                if (it.resolvedType != null && it.resolvedType.extendsViewStub()) {
446de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
447de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
44859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                if (it.supportsTag() && it.tag != null &&
44959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        (rootTagsSupported || it.tag.startsWith("binding_"))) {
45059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    val originalTag = it.originalTag;
451dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
45292a428505b9102bc0560d2d5be1768da097909c2George Mount                    if (originalTag != null && !originalTag.startsWith("@{")) {
45359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        tagValue = "\"$originalTag\""
454dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
45559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            var packageName = layoutBinder.modulePackage
456dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
457dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
45800da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
459dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
460dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
46159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            tagValue = "root.getResources().getString($packageName.R.string.$resourceId)"
46200da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
46300da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
46459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("this.${it.fieldName}.setTag($tagValue);")
46559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                } else if (it.tag != null && !it.tag.startsWith("binding_") &&
46659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    it.originalTag != null) {
46759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    L.e(ErrorMessages.ROOT_TAG_NOT_SUPPORTED, it.originalTag)
4687551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
469d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
470d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4714d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount        tab("setRootTag(root);")
472dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
4730fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
474d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
475d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
476dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
47759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        if (!target.isUsed) {
478dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
479dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
48059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val index = indices[target] ?: throw IllegalStateException("Unknown binding target")
48159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val variableName = "bindings[$index]"
482dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
483dea555cf42dc3583604699c8c018d22681f56166George Mount        }
484dea555cf42dc3583604699c8c018d22681f56166George Mount    }
485dea555cf42dc3583604699c8c018d22681f56166George Mount
486d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
4877551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
4887551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
48959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val fs = FlagSet(layoutBinder.model.invalidateAnyBitSet,
49059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    layoutBinder.model.flagBucketCount);
4911c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
49259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                for (i in (0..(mDirtyFlags.buckets.size - 1))) {
4931c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
4941c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
4951c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
49659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            includedBinders.filter{it.isUsed }.forEach { binder ->
4977551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
4987551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
4992f64c44e4fa296cf658ca986c095eab62f82a31dYigit Boyar            tab("requestRebind();");
500d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5010fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
502d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
503d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
504447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    fun declareHasPendingBindings()  = kcode("") {
505447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("@Override")
506447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("public boolean hasPendingBindings() {") {
50759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            if (mDirtyFlags.buckets.size > 0) {
508447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("synchronized(this) {") {
50959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    val flagCheck = 0.rangeTo(mDirtyFlags.buckets.size - 1).map {
510447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                            "${mDirtyFlags.localValue(it)} != 0"
511447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }.joinToString(" || ")
51259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("if ($flagCheck) {") {
513447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                        tab("return true;")
514447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }
515447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("}")
516447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
517447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
518447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
51959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            includedBinders.filter{it.isUsed }.forEach { binder ->
520447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("if (${binder.fieldName}.hasPendingBindings()) {") {
521447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("return true;")
522447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
523447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
524447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
525447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            tab("return false;")
526447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        }
527447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("}")
528447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    }
529447971abca811b11b8c1d8e7bfaa294856d03c16George Mount
530d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
5310fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
532d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
5335bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
53459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab ("case ${it.name.br()} :") {
53559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        tab("${it.setterName}((${it.resolvedType.toJavaCode()}) variable);")
536d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
537d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
538d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
53959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                val declaredOnly = variables.filter { !it.isUsed && it.isDeclared };
54023910cf498c35704a03ba4f3889de2ab97ccbe21George Mount                declaredOnly.forEachIndexed { i, identifierExpr ->
54159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab ("case ${identifierExpr.name.br()} :") {
54259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        if (i == declaredOnly.size - 1) {
54323910cf498c35704a03ba4f3889de2ab97ccbe21George Mount                            tab("return true;")
54423910cf498c35704a03ba4f3889de2ab97ccbe21George Mount                        }
54523910cf498c35704a03ba4f3889de2ab97ccbe21George Mount                    }
54623910cf498c35704a03ba4f3889de2ab97ccbe21George Mount                }
547d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
548d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
549d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
550d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5510fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
552d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
553d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
554d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
55559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        variables.filterNot{it.isUsed }.forEach {
55659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public void ${it.setterName}(${it.resolvedType.toJavaCode()} ${it.readableName}) {") {
5575bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
5585bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5595bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5605bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
56159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public ${it.resolvedType.toJavaCode()} ${it.getterName}() {") {
56259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("return ${it.defaultValue};")
5635bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5645bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5655bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
5665bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
56759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            if (it.userDefinedType != null) {
56859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                nl("public void ${it.setterName}(${it.resolvedType.toJavaCode()} ${it.readableName}) {") {
56959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    if (it.isObservable) {
57059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        tab("updateRegistration(${it.id}, ${it.readableName});");
57118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
572019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.readableName};")
57318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
57418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
5751c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("synchronized(this) {") {
5761c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
57759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            tab("${mDirtyFlags.localName}$suffix |= ${flagSet.localValue(index)};")
5781c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        }
5791c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    } tab ("}")
58018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
58218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
58318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
58459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                nl("public ${it.resolvedType.toJavaCode()} ${it.getterName}() {") {
58518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
586d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
58718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
590d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
591d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
592d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
59334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
59434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
5954c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
59659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                model.observables.forEach {
59759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("case ${it.id} :") {
59859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        tab("return ${it.onChangeName}((${it.resolvedType.toJavaCode()}) object, fieldId);")
599d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
600d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
601d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
602d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
603d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
604d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
60534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
60634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
607d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
60859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        model.observables.forEach {
60959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("private boolean ${it.onChangeName}(${it.resolvedType.toJavaCode()} ${it.readableName}, int fieldId) {") {
610d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
61159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.parents.filterIsInstance(FieldAccessExpr::class.java)
612c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount                    accessedFields.filter { it.hasBindableAnnotations() }
61388ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar                            .groupBy { it.brName }
614d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
61588ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar                                // If two expressions look different but resolve to the same method,
61688ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar                                // we are not yet able to merge them. This is why we merge their
61788ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar                                // flags below.
61888ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar                                tab("case ${it.key}:") {
6191c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    tab("synchronized(this) {") {
62088ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar                                        val flagSet = it.value.foldRight(FlagSet()) { l, r -> l.invalidateFlagSet.or(r) }
62188ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar
62288ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar                                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
62388ce44ccc65e74a8553244ca246cc9f4c48483e0Yigit Boyar                                            tab("${mDirtyFlags.localValue(index)} |= ${flagSet.localValue(index)};")
6241c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        }
6251c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    } tab("}")
626d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
627d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
628d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
629d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
63043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
6321c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        tab("synchronized(this) {") {
6331c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            mDirtyFlags.mapOr(flagSet) { suffix, index ->
63459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                                tab("${mDirtyFlags.localName}$suffix |= ${flagSet.localValue(index)};")
6351c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            }
6361c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        } tab("}")
637d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
638d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
639d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
640d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
641d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
642d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
643d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
64434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
64534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
646d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
647d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
648d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
649d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
650dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
65159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        layoutBinder.sortedTargets.filter {it.isUsed && (oneLayout || it.id == null)}.forEach {
652dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
65359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            if (oneLayout && it.id != null) {
654dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
655dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
656dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
657dea555cf42dc3583604699c8c018d22681f56166George Mount            }
65859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("$access final ${it.interfaceClass} ${it.fieldName};")
659d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
660d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
661d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
662d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
6635bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
66459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("private ${it.resolvedType.toJavaCode()} ${it.fieldName};")
665d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
666d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
667d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
66820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    fun declareBoundValues() = kcode("// values") {
66959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        layoutBinder.sortedTargets.filter { it.isUsed }
67059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                .flatMap { it.bindings }
67120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .filter { it.requiresOldValue() }
67259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                .flatMap{ it.componentExpressions.toArrayList() }
67320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .groupBy { it }
67420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .forEach {
67559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    val expr = it.key
67659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    nl("private ${expr.resolvedType.toJavaCode()} ${expr.oldValueName};")
67720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                }
67820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    }
67920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
680716ba89e7f459f49ea85070d4710c1d79d715298George Mount    fun declareListeners() = kcode("// listeners") {
68159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        model.exprMap.values.filter {
682793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            it is ListenerExpr
683716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }.groupBy { it }.forEach {
684793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            val expr = it.key as ListenerExpr
685716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("private ${expr.listenerClassName} ${expr.fieldName};")
686716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
687716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
688716ba89e7f459f49ea85070d4710c1d79d715298George Mount
689d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
690d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
691de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
6920fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
69359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                app(" ", if(flag.isDynamic) null else "static final");
69459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                app(" ", " ${flag.type} ${flag.localName}$suffix = ${longToBinary(value)};")
695d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
696d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
697d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
698d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
699d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
70059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        if (model.flagMapping != null) {
70159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val mapping = model.flagMapping
702d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
703d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
704d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
705d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
706d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
707d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
708d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7094c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
7100fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
711e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        nl("protected void executeBindings() {") {
712d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
71359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tmpDirtyFlags.localName = "dirtyFlags";
71459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            for (i in (0..mDirtyFlags.buckets.size - 1)) {
7151c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = 0;")
716d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
7171c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
71859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                for (i in (0..mDirtyFlags.buckets.size - 1)) {
7191c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
7201c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = 0;")
7211c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
7221c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
72359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            model.pendingExpressions.filter { it.needsLocalField }.forEach {
72459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("${it.resolvedType.toJavaCode()} ${it.executePendingLocalName} = ${if (it.isVariable()) it.fieldName else it.defaultValue};")
725d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
726b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar            L.d("writing executePendingBindings for %s", className)
727d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
72859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                val batch = ExprModel.filterShouldRead(model.pendingExpressions).toArrayList()
729a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                val justRead = arrayListOf<Expr>()
730b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                L.d("batch: %s", batch)
731d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
732a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val readNow = batch.filter { it.shouldReadNow(justRead) }
733d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
734d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
735d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
73659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    L.d("new read now. batch size: %d, readNow size: %d", batch.size, readNow.size)
737a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    nl(readWithDependants(readNow, justRead, batch, tmpDirtyFlags))
738a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    batch.removeAll(justRead)
739d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7400fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
741a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } while (model.markBitsRead())
7427b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            // verify everything is read.
74359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val batch = ExprModel.filterShouldRead(model.pendingExpressions).toArrayList()
7447b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            if (batch.isNotEmpty()) {
7457b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                L.e("could not generate code for %s. This might be caused by circular dependencies."
74659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        + "Please report on b.android.com. %d %s %s", layoutBinder.layoutname,
74759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        batch.size, batch[0], batch[0].toCode().generate())
7487b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            }
749d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
75059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            layoutBinder.sortedTargets.filter { it.isUsed }
75159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    .flatMap { it.bindings }
752a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    .groupBy {
75359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        "${tmpDirtyFlags.mapOr(it.expr.dirtyFlagSet) { suffix, index ->
75459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            "(${tmpDirtyFlags.localValue(index)} & ${it.expr.dirtyFlagSet.localValue(index)}) != 0"
755a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }.joinToString(" || ") }"
756a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }.forEach {
757a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("if (${it.key}) {") {
75859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    it.value.groupBy { Math.max(1, it.minApi) }.forEach {
759a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val setterValues = kcode("") {
760d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
761a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                val fieldName: String
76259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                                if (binding.target.viewClass.
76359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                                        equals(binding.target.interfaceType)) {
76459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                                    fieldName = "this.${binding.target.fieldName}"
76534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
76659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                                    fieldName = "((${binding.target.viewClass}) this.${binding.target.fieldName})"
76734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
768a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                tab(binding.toJavaCode(fieldName, "this.mBindingComponent")).app(";")
769a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
770a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
771a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        tab("// api target ${it.key}")
772a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (it.key > 1) {
773a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("if(getBuildSdkInt() >= ${it.key}) {") {
774a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                app("", setterValues)
775d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
776a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("}")
777a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        } else {
778a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            app("", setterValues)
77920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }
78020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    }
781a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
782a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
783a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }
784a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
78520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
78659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            layoutBinder.sortedTargets.filter { it.isUsed }
78759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    .flatMap { it.bindings }
78820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .filter { it.requiresOldValue() }
78959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    .groupBy {"${tmpDirtyFlags.mapOr(it.expr.dirtyFlagSet) { suffix, index ->
79059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        "(${tmpDirtyFlags.localValue(index)} & ${it.expr.dirtyFlagSet.localValue(index)}) != 0"
791a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }.joinToString(" || ")
792a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }"}.forEach {
793a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("if (${it.key}) {") {
79459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    it.value.groupBy { it.expr }.map { it.value.first() }.forEach {
79559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        it.componentExpressions.forEach { expr ->
796a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab("this.${expr.oldValueName} = ${expr.toCode().generate()};")
797d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
798d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
799a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
800a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
801a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }
80259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            includedBinders.filter{it.isUsed }.forEach { binder ->
8034c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
8047551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
80559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            layoutBinder.sortedTargets.filter{
80659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                it.isUsed && it.resolvedType != null && it.resolvedType.extendsViewStub()
807de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }.forEach {
808de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("if (${it.fieldName}.getBinding() != null) {") {
809de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("${it.fieldName}.getBinding().executePendingBindings();")
810de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
811de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("}")
812de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
813d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
8140fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
815d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
816d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
817a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    fun readWithDependants(expressionList: List<Expr>, justRead: MutableList<Expr>,
818a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            batch: MutableList<Expr>, tmpDirtyFlags: FlagSet,
819a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            inheritedFlags: FlagSet? = null) : KCode = kcode("") {
820a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount        expressionList.groupBy { it.shouldReadFlagSet }.forEach {
821a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val flagSet = it.key
822a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
823a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val expressions = it.value
824a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
825a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
826a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            }.joinToString(" || ")
827a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            })"
828a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            val readCode = kcode("") {
829a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                val dependants = ArrayList<Expr>()
830a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                expressions.groupBy { condition(it) }.forEach {
831a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val condition = it.key
8320b6d118e6eeb3bc100fc6a6e66016ab812cb2783Yigit Boyar                    val assignedValues = it.value.filter { it.needsLocalField && !it.isVariable() }
833a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    if (!assignedValues.isEmpty()) {
834a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        val assignment = kcode("") {
835a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            assignedValues.forEach { expr: Expr ->
83659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                                tab("// read ${expr.uniqueKey}")
837a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                tab("${expr.executePendingLocalName}").app(" = ", expr.toFullCode()).app(";")
838a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
839a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
840a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (condition != null) {
84159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            tab("if ($condition) {") {
842a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                app("", assignment)
843a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
844a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            tab ("}")
845a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        } else {
846a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            app("", assignment)
847d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
84859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        it.value.filter { it.isObservable }.forEach { expr: Expr ->
84959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            tab("updateRegistration(${expr.id}, ${expr.executePendingLocalName});")
8509e7a4ce47ae5f4428f7630fe03a7ad66d06177fbGeorge Mount                        }
851a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    }
852a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
853a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    it.value.forEach { expr: Expr ->
854a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        justRead.add(expr)
85559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        L.d("%s / readWithDependants %s", className, expr.uniqueKey);
856a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        L.d("flag set:%s . inherited flags: %s. need another if: %s", flagSet, inheritedFlags, needsIfWrapper);
857a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
858a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        // if I am the condition for an expression, set its flag
85959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        expr.dependants.filter {
86059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            !it.isConditional && it.dependant is TernaryExpr &&
86159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                                    (it.dependant as TernaryExpr).pred == expr
86259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        }.map { it.dependant }.groupBy {
863eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                            // group by when those ternaries will be evaluated (e.g. don't set conditional flags for no reason)
86459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            val ternaryBitSet = it.shouldReadFlagsWithConditionals
86559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            val isBehindTernary = ternaryBitSet.nextSetBit(model.invalidateAnyFlagIndex) == -1
866eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                            if (!isBehindTernary) {
867eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                val ternaryFlags = it.shouldReadWithConditionalsFlagSet
868eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                "if(${tmpDirtyFlags.mapOr(ternaryFlags){ suffix, index ->
869eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                    "(${tmpDirtyFlags.localValue(index)} & ${ternaryFlags.localValue(index)}) != 0"
870eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                }.joinToString(" || ")}) {"
871eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                            } else {
872eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                // TODO if it is behind a ternary, we should set it when its predicate is elevated
873eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                // Normally, this would mean that there is another code path to re-read our current expression.
874eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                // Unfortunately, this may not be true due to the coverage detection in `expr#markAsReadIfDone`, this may never happen.
875eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                // for v1.0, we'll go with always setting it and suffering an unnecessary calculation for this edge case.
876eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                // we can solve this by listening to elevation events from the model.
877eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                ""
878a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
879eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                        }.forEach {
880eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                            val hasAnotherIf = it.key != ""
881eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                            if (hasAnotherIf) {
882eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                tab(it.key) {
883eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                    tab("if (${expr.executePendingLocalName}) {") {
884eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        it.value.forEach {
885eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                            val set = it.getRequirementFlagSet(true)
886eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                            mDirtyFlags.mapOr(set) { suffix, index ->
887eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                                tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
888eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                            }
889eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        }
890eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                    }
891eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                    tab("} else {") {
892eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        it.value.forEach {
893eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                            val set = it.getRequirementFlagSet(false)
894eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                            mDirtyFlags.mapOr(set) { suffix, index ->
895eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                                tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
896eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                            }
897eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        }
898eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                    }.tab("}")
899eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                }.app("}")
900eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                            } else {
901eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                tab("if (${expr.executePendingLocalName}) {") {
902eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                    it.value.forEach {
903eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        val set = it.getRequirementFlagSet(true)
904eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        mDirtyFlags.mapOr(set) { suffix, index ->
905eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
906eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        }
907a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    }
908a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                }
909eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                tab("} else {") {
910eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                    it.value.forEach {
911eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        val set = it.getRequirementFlagSet(false)
912eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        mDirtyFlags.mapOr(set) { suffix, index ->
913eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
914eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                        }
915eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                    }
916eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar                                } app("}")
917a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            }
918a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
91959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        val chosen = expr.dependants.filter {
92059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            val dependant = it.dependant
921a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                            batch.contains(dependant) &&
92259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                                    dependant.shouldReadFlagSet.andNot(flagSet).isEmpty &&
923a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                                    dependant.shouldReadNow(justRead)
924a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        }
925a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                        if (chosen.isNotEmpty()) {
92659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                            dependants.addAll(chosen.map { it.dependant })
9270fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
9280fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
929a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
930a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                if (dependants.isNotEmpty()) {
931a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
932a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    nl(readWithDependants(dependants, justRead, batch, tmpDirtyFlags, nextInheritedFlags))
933a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                }
934d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
9350fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
936a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            if (needsIfWrapper) {
937a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab(ifClause) {
938a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    app(" {")
939a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                    app("", readCode)
940d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
941a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                tab("}")
942a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } else {
943a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                app("", readCode)
944d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
945d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
946a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    }
947a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount
948a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount    fun condition(expr : Expr) : String? {
949a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount        if (expr.canBeEvaluatedToAVariable() && !expr.isVariable()) {
950a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            // create an if case for all dependencies that might be null
95159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val nullables = expr.dependencies.filter {
95259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                it.isMandatory && it.other.resolvedType.isNullable
95359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            }.map { it.other }
95459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            if (!expr.isEqualityCheck && nullables.isNotEmpty()) {
955a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                return "${nullables.map { "${it.executePendingLocalName} != null" }.joinToString(" && ")}"
956a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            } else {
957a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount                return null
958d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
959d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
960a0820baa03e731f274ef55c5541e9fc101bbaddbGeorge Mount            return null
961d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
962d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
963716ba89e7f459f49ea85070d4710c1d79d715298George Mount
964716ba89e7f459f49ea85070d4710c1d79d715298George Mount    fun declareListenerImpls() = kcode("// Listener Stub Implementations") {
96559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        model.exprMap.values.filter {
96659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            it.isUsed && it is ListenerExpr
967716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }.groupBy { it }.forEach {
968793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            val expr = it.key as ListenerExpr
96959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            val listenerType = expr.resolvedType;
970793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            val extendsImplements : String
97159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            if (listenerType.isInterface) {
972793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                extendsImplements = "implements"
973793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            } else {
974793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                extendsImplements = "extends"
975793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount            }
97659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public static class ${expr.listenerClassName} $extendsImplements ${listenerType.canonicalName}{") {
97759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                if (expr.child.isDynamic) {
97859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("private ${expr.child.resolvedType.toJavaCode()} value;")
97959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("public ${expr.listenerClassName} setValue(${expr.child.resolvedType.toJavaCode()} value) {") {
980716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("this.value = value;")
981716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        tab("return value == null ? null : this;")
982716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }
983716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    tab("}")
984716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
98559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                val listenerMethod = expr.method
98659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                val parameterTypes = listenerMethod.parameterTypes
987793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                val returnType = listenerMethod.getReturnType(parameterTypes.toArrayList())
988793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                tab("@Override")
98959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("public $returnType ${listenerMethod.name}(${
990716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    parameterTypes.withIndex().map {
991716ba89e7f459f49ea85070d4710c1d79d715298George Mount                        "${it.value.toJavaCode()} arg${it.index}"
992716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }.joinToString(", ")
993793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                }) {") {
994793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    val obj : String
99559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    if (expr.child.isDynamic) {
996793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        obj = "this.value"
997793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    } else {
99859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                        obj = expr.child.toCode().generate();
999793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    }
1000793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    val returnStr : String
100159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    if (!returnType.isVoid) {
1002793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        returnStr = "return "
1003793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    } else {
1004793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        returnStr = ""
1005716ba89e7f459f49ea85070d4710c1d79d715298George Mount                    }
1006793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    val args = parameterTypes.withIndex().map {
1007793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                        "arg${it.index}"
1008793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                    }.joinToString(", ")
100959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("$returnStr$obj.${expr.name}($args);")
1010716ba89e7f459f49ea85070d4710c1d79d715298George Mount                }
1011793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount                tab("}")
1012716ba89e7f459f49ea85070d4710c1d79d715298George Mount            }
1013716ba89e7f459f49ea85070d4710c1d79d715298George Mount            nl("}")
1014716ba89e7f459f49ea85070d4710c1d79d715298George Mount        }
1015716ba89e7f459f49ea85070d4710c1d79d715298George Mount    }
101643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
1017dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
101859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        nl("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
1019e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
1020e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        }
1021e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount        nl("}")
102259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        nl("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
102359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tab("return android.databinding.DataBindingUtil.<$baseClassName>inflate(inflater, ${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname}, root, attachToRoot, bindingComponent);")
1024081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        }
1025081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("}")
102659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        if (!layoutBinder.isMerge) {
102759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public static $baseClassName inflate(android.view.LayoutInflater inflater) {") {
1028e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
1029e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1030e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("}")
103159229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
103259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("return bind(inflater.inflate(${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname}, null, false), bindingComponent);")
103396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
103496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
103559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public static $baseClassName bind(android.view.View view) {") {
1036e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
1037e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1038e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            nl("}")
103959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public static $baseClassName bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
104059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("if (!\"${layoutBinder.tag}_0\".equals(view.getTag())) {") {
1041f80b08430f11515ff944f89006799f21545602b9George Mount                    tab("throw new RuntimeException(\"view tag isn't correct on view:\" + view.getTag());")
104296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
104396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("}")
104459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("return new $baseClassName(bindingComponent, view);")
104596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
104696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
1047dea555cf42dc3583604699c8c018d22681f56166George Mount        }
1048dea555cf42dc3583604699c8c018d22681f56166George Mount    }
1049dea555cf42dc3583604699c8c018d22681f56166George Mount
10508b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    /**
10518b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar     * When called for a library compilation, we do not generate real implementations
10528b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar     */
10538b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar    public fun writeBaseClass(forLibrary : Boolean) : String =
105459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar        kcode("package ${layoutBinder.`package`};") {
1055fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
1056fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
1057fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
105859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            nl("public abstract class $baseClassName extends ViewDataBinding {")
105959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            layoutBinder.sortedTargets.filter{it.id != null}.forEach {
106059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                tab("public final ${it.interfaceClass} ${it.fieldName};")
106134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
106234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
106359229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tab("protected $baseClassName(android.databinding.DataBindingComponent bindingComponent, android.view.View root_, int localFieldCount") {
106459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                layoutBinder.sortedTargets.filter{it.id != null}.forEach {
106559229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab(", ${it.interfaceClass} ${it.constructorParamName}")
106634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
106734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
106834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
1069e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("super(bindingComponent, root_, localFieldCount);")
107059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                layoutBinder.sortedTargets.filter{it.id != null}.forEach {
1071019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.constructorParamName};")
107234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
10734c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
10744c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
10754c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
107643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
107759229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                if (it.userDefinedType != null) {
107859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.userDefinedType, model.imports)
107959229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("public abstract void ${it.setterName}($type ${it.readableName});")
108018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
108143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
108259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tab("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
1083e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
1084e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1085e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
108659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tab("public static $baseClassName inflate(android.view.LayoutInflater inflater) {") {
1087e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
1088e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1089e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
109059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tab("public static $baseClassName bind(android.view.View view) {") {
10918b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
10928b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
10938b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
1094e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
10958b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
109643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
10974c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
109859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tab("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
10998b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
11008b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
11018b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
110259229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("return DataBindingUtil.<$baseClassName>inflate(inflater, ${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname}, root, attachToRoot, bindingComponent);")
11038b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
11044c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
11054c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
110659229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tab("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
1107e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                if (forLibrary) {
1108e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                    tab("return null;")
1109e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                } else {
111059229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("return DataBindingUtil.<$baseClassName>inflate(inflater, ${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname}, null, false, bindingComponent);")
1111e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount                }
1112e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            }
1113e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount            tab("}")
111459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar            tab("public static $baseClassName bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
11158b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                if (forLibrary) {
11168b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                    tab("return null;")
11178b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                } else {
111859229481aec5a284d322a2ca80dff836485feb0cYigit Boyar                    tab("return ($baseClassName)bind(bindingComponent, view, ${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname});")
11198b1da958f181639d33dfaa907c0ee66add2decd6Yigit Boyar                }
11204c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
11214c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
112243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
112343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
1124dea555cf42dc3583604699c8c018d22681f56166George Mount}
1125