LayoutBinderWriter.kt revision c6bcb7bf9cab139b3141c4644e5b3267deed5213
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
16fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.LayoutBinder
17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr
18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport kotlin.properties.Delegates
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.joinToCamelCaseAsVar
20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.BindingTarget
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.IdentifierExpr
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.util.Log
23d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.BitSet
24fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel
25d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.Arrays
26c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.tool.expr.BitShiftExpr
27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.TernaryExpr
28fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.FieldAccessExpr
29fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ComparisonExpr
30fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.GroupExpr
31c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.tool.expr.InstanceOfExpr
32fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.MathExpr
33fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.MethodCallExpr
34fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.StaticIdentifierExpr
35fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.SymbolExpr
36c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.tool.expr.UnaryExpr
37fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.androidId
38fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.lazy
39fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.br
40fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ResourceExpr
41fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.BracketExpr
42fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.Callable
43fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.CastExpr
44fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer
4596e1c821dd446d1ed78f8ae61131550588f60a24George Mountimport java.util.ArrayList
4634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.HashMap
4743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]").map{ it.trim() }.joinToCamelCaseAsVar()
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val usedFieldNames = hashSetOf<String>()
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val localizedFlags = arrayListOf<FlagSet>()
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun localizeFlag(set : FlagSet, name:String) : FlagSet {
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        localizedFlags.add(set)
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val result = getUniqueFieldName(name)
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        set.setLocalName(result)
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return set
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun getUniqueFieldName(base : String) : String {
62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var candidate = base
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var i = 0
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        while (usedFieldNames.contains(candidate)) {
65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            i ++
66d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            candidate = base + i
67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        usedFieldNames.add(candidate)
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return candidate
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
73de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval ExprModel.ext by Delegates.lazy { target : ExprModel ->
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    ExprModelExt()
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.getUniqueFieldName(base : String) : String = ext.getUniqueFieldName(base)
78d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
81de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.readableUniqueName by Delegates.lazy { target: BindingTarget ->
8200da715547ee7d5d38a3b8576090ca427a94daa5George Mount    val variableName : String
8300da715547ee7d5d38a3b8576090ca427a94daa5George Mount    if (target.getId() == null) {
8496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        variableName = "boundView" + indexFromTag(target.getTag())
8500da715547ee7d5d38a3b8576090ca427a94daa5George Mount    } else {
8600da715547ee7d5d38a3b8576090ca427a94daa5George Mount        variableName = target.getId().androidId().stripNonJava()
8700da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
8800da715547ee7d5d38a3b8576090ca427a94daa5George Mount    target.getModel().ext.getUniqueFieldName(variableName)
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
907551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
91de38dd3ef0577d25b2d59863603abe5750d0c231George Mountfun BindingTarget.superConversion(variable : String) : String {
9296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    if (getResolvedType() != null && getResolvedType().extendsViewStub()) {
93de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "new android.databinding.ViewStubProxy((android.view.ViewStub) ${variable})"
94de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
95de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "(${interfaceType}) ${variable}"
96de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
97de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
98de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
99de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.fieldName by Delegates.lazy { target : BindingTarget ->
10034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    if (target.getFieldName() == null) {
10134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        if (target.getId() == null) {
10234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.setFieldName("m${target.readableUniqueName.capitalize()}")
10334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        } else {
10434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.androidId.stripNonJava();
10534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.setFieldName(target.readableUniqueName);
10634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
10734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
10834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    target.getFieldName();
109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
111de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.getterName by Delegates.lazy { target : BindingTarget ->
112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "get${target.readableUniqueName.capitalize()}"
113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
115de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.androidId by Delegates.lazy { target : BindingTarget ->
11643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    "R.id.${target.getId().androidId()}"
117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
119de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.interfaceType by Delegates.lazy { target : BindingTarget ->
120de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    if (target.getResolvedType() != null && target.getResolvedType().extendsViewStub()) {
121de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        "android.databinding.ViewStubProxy"
122de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
123de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        target.getInterfaceType()
124de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
125de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
126de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
127de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableUniqueName by Delegates.lazy { expr : Expr ->
12843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    Log.d { "readableUniqueName for ${expr.getUniqueKey()}" }
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val stripped = "${expr.getUniqueKey().stripNonJava()}"
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getModel().ext.getUniqueFieldName(stripped)
131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
133de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableName by Delegates.lazy { expr : Expr ->
134de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    Log.d { "readableUniqueName for ${expr.getUniqueKey()}" }
135de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "${expr.getUniqueKey().stripNonJava()}"
136de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
137de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
138de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.fieldName by Delegates.lazy { expr : Expr ->
139de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "m${expr.readableName.capitalize()}"
140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
142de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.hasFlag by Delegates.lazy { expr : Expr ->
143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getId() < expr.getModel().getInvalidateableFieldLimit()
144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
146de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.localName by Delegates.lazy { expr : Expr ->
147d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if(expr.isVariable()) expr.fieldName else "${expr.readableUniqueName}"
148d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
150de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.setterName by Delegates.lazy { expr : Expr ->
151de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "set${expr.readableName.capitalize()}"
152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
154de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.onChangeName by Delegates.lazy { expr : Expr ->
155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "onChange${expr.readableUniqueName.capitalize()}"
156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
158de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.getterName by Delegates.lazy { expr : Expr ->
159de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "get${expr.readableName.capitalize()}"
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
162de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagName by Delegates.lazy { expr : Expr ->
163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}"
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
166de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.shouldReadFlagName by Delegates.lazy { expr : Expr ->
167d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlagRead${expr.readableUniqueName.capitalize()}"
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
170de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagName by Delegates.lazy { expr : Expr ->
171d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}Invalid"
172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
174de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlagPrefix by Delegates.lazy { expr : Expr ->
175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}Is"
176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.toCode(full : Boolean = false) : KCode {
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val it = this
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if (isDynamic() && !full) {
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return kcode(localName)
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return when (it) {
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is ComparisonExpr -> kcode("") {
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getLeft().toCode())
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(it.getOp())
188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getRight().toCode())
189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
190c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount        is InstanceOfExpr -> kcode("") {
191c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount            app("", it.getExpr().toCode())
192c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount            app(" instanceof ")
193c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount            app("", it.getType().toJavaCode())
194c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount        }
195d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is FieldAccessExpr -> kcode("") {
196a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount            app("", it.getChild().toCode())
197e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount            if (it.getGetter().type == Callable.Type.FIELD) {
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(".", it.getGetter().name)
199d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } else {
200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(".", it.getGetter().name).app("()")
201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is GroupExpr -> kcode("(").app("", it.getWrapped().toCode()).app(")")
204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is StaticIdentifierExpr -> kcode(it.getResolvedType().toJavaCode())
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is IdentifierExpr -> kcode(it.localName)
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is MathExpr -> kcode("") {
207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getLeft().toCode())
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(it.getOp())
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getRight().toCode())
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
211c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount        is UnaryExpr -> kcode("") {
212c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount            app(it.getOp(), it.getExpr().toCode())
213c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount        }
214c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount        is BitShiftExpr -> kcode("") {
215c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount            app("", it.getLeft().toCode())
216c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount            app(it.getOp())
217c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount            app("", it.getRight().toCode())
218c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount        }
219d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is MethodCallExpr -> kcode("") {
220d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getTarget().toCode())
221d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(".", it.getGetter().name)
222d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("(")
223d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            var first = true
224d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            it.getArgs().forEach {
225d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                apps(if (first) "" else ",", it.toCode())
226d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                first = false
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
228d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(")")
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is SymbolExpr -> kcode(it.getText()) // TODO
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is TernaryExpr -> kcode("") {
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getPred().toCode())
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("?", it.getIfTrue().toCode())
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(":", it.getIfFalse().toCode())
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
236c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        is ResourceExpr -> kcode("") {
237c752a5f795baf6df435ef60881316cb748df407cGeorge Mount            app("", it.toJava())
238c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        }
2395cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        is BracketExpr -> kcode("") {
2405cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            app("", it.getTarget().toCode())
2415cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            val bracketType = it.getAccessor();
2425cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            when (bracketType) {
2435cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.ARRAY -> {
2445cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("[", it.getArg().toCode())
2455cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("]")
2465cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2475cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.LIST -> {
2485cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(".get(")
2495cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    if (it.argCastsInteger()) {
2505cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                        app("(Integer)")
2515cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    }
2525cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("", it.getArg().toCode())
2535cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(")")
2545cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2555cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.MAP -> {
2565cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(".get(", it.getArg().toCode())
2575cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(")")
2585cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2595cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
2605cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
261e4b93061ac703e48fc2c9994c9059ed016f05559George Mount        is CastExpr -> kcode("") {
262e4b93061ac703e48fc2c9994c9059ed016f05559George Mount            app("(", it.getCastType())
263e4b93061ac703e48fc2c9994c9059ed016f05559George Mount            app(") ", it.getCastExpr().toCode())
264e4b93061ac703e48fc2c9994c9059ed016f05559George Mount        }
265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else -> kcode("//NOT IMPLEMENTED YET")
266d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
268d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
270d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
271d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
272d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
273d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
274d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
275de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagSet by Delegates.lazy { expr : Expr ->
276d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
278d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
279de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagSet by Delegates.lazy { expr : Expr ->
280d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getId())
281d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
282d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
283de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.shouldReadFlagSet by Delegates.lazy { expr : Expr ->
284d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
285d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
286d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
287de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlags by Delegates.lazy { expr : Expr ->
288d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
289d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
290d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
291d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
293d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
294d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
295d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
296d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
297d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
298d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
299d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
300d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
301d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
302d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getBitSuffix(bitIndex : Int) : String {
303d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val word = bitIndex / FlagSet.sBucketSize
304d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return getWordSuffix(word)
305d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
306d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
307d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
308d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
309d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
310d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
311d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
312d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (getLocalName() == null) binaryCode(bucketIndex)
313d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
314d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
315d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
316d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
317d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
318d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun longToBinary(l : Long) =
319d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        "0b${java.lang.Long.toBinaryString(l)}L"
320d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
321d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
322d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
323d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
324d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
325d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
326d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
327d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
328d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
329d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
330d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
331d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
332d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
33396e1c821dd446d1ed78f8ae61131550588f60a24George Mountfun indexFromTag(tag : String) : kotlin.Int {
33496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    val startIndex : kotlin.Int
3357ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    if (tag.startsWith("binding_")) {
3367ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        startIndex = "binding_".length();
33796e1c821dd446d1ed78f8ae61131550588f60a24George Mount    } else {
33896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        startIndex = tag.lastIndexOf('_') + 1
33996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
34096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    return Integer.parseInt(tag.substring(startIndex))
34196e1c821dd446d1ed78f8ae61131550588f60a24George Mount}
34296e1c821dd446d1ed78f8ae61131550588f60a24George Mount
34343596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
344d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
34534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
34643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
34743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
34843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
34943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
35043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
35143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
352d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
353d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
35443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
355dea555cf42dc3583604699c8c018d22681f56166George Mount    val className = layoutBinder.getImplementationName()
356d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
35743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val identifiers by Delegates.lazy {
35843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        dynamics.filter { it is IdentifierExpr }
35943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
360d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
361dea555cf42dc3583604699c8c018d22681f56166George Mount    val baseClassName = "${layoutBinder.getClassName()}"
362d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3637551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
3647551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
3657551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
3667551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
36743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
36843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
36943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
370d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3715bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
3725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
3735bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
374d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
37596e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public fun write(minSdk : kotlin.Int) : String  {
3765bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
37734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
3785bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
379a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
380a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
3815bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
382dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
383dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
384dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends ${baseClassName}"
385dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
386dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends android.databinding.ViewDataBinding"
387dea555cf42dc3583604699c8c018d22681f56166George Mount            }
388dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public class ${classDeclaration} {") {
3894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
3905bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
3915bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
39296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab(declareConstructor(minSdk))
3935bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
3945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
3955bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
3965bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
3975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3994c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
4005bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
4015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
402dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
403dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
404dea555cf42dc3583604699c8c018d22681f56166George Mount                }
4055bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
4065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
4075bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
4085bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
4095bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
4105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
41134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
41296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getBindingTargets().filter{
41396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && it.getTag() != null && !it.isBinder()
41434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
41596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        taggedViews.forEach {
41696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it, indexFromTag(it.getTag()))
41796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
41896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val indexStart = maxIndex() + 1
41996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getBindingTargets().filter{
42096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && !taggedViews.contains(it)
42196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }.withIndex().forEach {
42296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it.value, it.index + indexStart)
42334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
42434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
4254c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
42696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        nl("private static final android.databinding.ViewDataBinding.IncludedLayoutIndex[][] sIncludes;")
4274c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
4284c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
4294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
4304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
4314c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
43200da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
43396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val numBindings = layoutBinder.getBindingTargets().filter{ it.isUsed() }.count()
43496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("sIncludes = new android.databinding.ViewDataBinding.IncludedLayoutIndex[${numBindings}][];")
43596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
43696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder() }.forEach {
43796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val includeTag = it.getTag();
43896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val parent = layoutBinder.getBindingTargets().firstOrNull {
43996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        it.isUsed() && !it.isBinder() && includeTag.equals(it.getTag())
44096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
44196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (parent == null) {
44296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        throw IllegalStateException("Could not find parent of include file")
44396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
44496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    var list = includeMap.get(parent)
44596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (list == null) {
44696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        list = ArrayList<BindingTarget>()
44796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.put(parent, list)
44896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
44996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    list.add(it)
4504c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
45196e1c821dd446d1ed78f8ae61131550588f60a24George Mount
45296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                includeMap.keySet().forEach {
45396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val index = indices.get(it)
45496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("sIncludes[${index}] = new android.databinding.ViewDataBinding.IncludedLayoutIndex[] {") {
45596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.get(it).forEach {
45696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            val bindingIndex = indices.get(it)
45796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            val layoutName = it.getIncludedLayout()
45896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            tab("new android.databinding.ViewDataBinding.IncludedLayoutIndex(\"${layoutName}\", ${bindingIndex}, R.layout.${layoutName}),")
45996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        }
46096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
46196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("};")
46296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
46396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
46496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val viewsWithIds = layoutBinder.getBindingTargets().filter {
46596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                it.isUsed() && !it.isBinder() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
46600da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
46796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (viewsWithIds.isEmpty()) {
4684c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
46900da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
4704c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
47196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                viewsWithIds.forEach {
47234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sViewsWithIds.put(${it.androidId}, ${indices.get(it)});")
4734c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
47400da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
4754c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
4764c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
4774c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
47896e1c821dd446d1ed78f8ae61131550588f60a24George Mount
47996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun maxIndex() : kotlin.Int {
48096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val maxIndex = indices.values().max()
48196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (maxIndex == null) {
48296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return -1
48396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
48496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return maxIndex
48596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
48696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
48796e1c821dd446d1ed78f8ae61131550588f60a24George Mount
48896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun declareConstructor(minSdk : kotlin.Int) = kcode("") {
48996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val bindingCount = maxIndex() + 1
49096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val parameterType : String
49196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val superParam : String
49296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (layoutBinder.isMerge()) {
49396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View[]"
49496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root[0]"
49596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
49696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View"
49796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root"
49896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
49996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val rootTagsSupported = minSdk >= 14
500dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
501dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
50296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public ${className}(${parameterType} root) {") {
50396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("this(${superParam}, mapBindings(root, ${bindingCount}, sIncludes, sViewsWithIds));")
504dea555cf42dc3583604699c8c018d22681f56166George Mount            }
505dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
50696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("private ${className}(${parameterType} root, Object[] bindings) {") {
50796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("super(${superParam}, ${model.getObservables().size()}") {
50896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    layoutBinder.getSortedTargets().filter { it.getId() != null }.forEach {
509dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
51034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
511dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
51234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
51334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
514dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
51596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public ${baseClassName}(${parameterType} root) {") {
51696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("super(${superParam}, ${model.getObservables().size()});")
51796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("final Object[] bindings = mapBindings(root, ${bindingCount}, sIncludes, sViewsWithIds);")
518dea555cf42dc3583604699c8c018d22681f56166George Mount            }
519dea555cf42dc3583604699c8c018d22681f56166George Mount        }
52096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        tab("setRootTag(root);")
52196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getSortedTargets().filter{it.isUsed()}
522dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
523dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!layoutBinder.hasVariations() || it.getId() == null) {
524dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
525dea555cf42dc3583604699c8c018d22681f56166George Mount            }
526dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!it.isBinder()) {
527de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                if (it.getResolvedType() != null && it.getResolvedType().extendsViewStub()) {
528de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
529de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
53096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (it.supportsTag() && it.getTag() != null &&
5317ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        (rootTagsSupported || it.getTag().startsWith("binding_"))) {
532dea555cf42dc3583604699c8c018d22681f56166George Mount                    val originalTag = it.getOriginalTag();
533dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
534dea555cf42dc3583604699c8c018d22681f56166George Mount                    if (originalTag != null) {
535dea555cf42dc3583604699c8c018d22681f56166George Mount                        tagValue = "\"${originalTag}\""
536dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
537dea555cf42dc3583604699c8c018d22681f56166George Mount                            var packageName = layoutBinder.getModulePackage()
538dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
539dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
54000da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
541dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
542dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
543dea555cf42dc3583604699c8c018d22681f56166George Mount                            tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
54400da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
54500da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
546dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab("this.${it.fieldName}.setTag(${tagValue});")
5477551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
548d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
549d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
550dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
5510fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
552d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
553d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
554dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
555dea555cf42dc3583604699c8c018d22681f56166George Mount        if (!target.isUsed()) {
556dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
557dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
55896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val index = indices.get(target)
559dea555cf42dc3583604699c8c018d22681f56166George Mount            if (index == null) {
56096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                throw IllegalStateException("Unknown binding target")
561dea555cf42dc3583604699c8c018d22681f56166George Mount            }
56296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val variableName = "bindings[${index}]"
563dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
564dea555cf42dc3583604699c8c018d22681f56166George Mount        }
565dea555cf42dc3583604699c8c018d22681f56166George Mount    }
566dea555cf42dc3583604699c8c018d22681f56166George Mount
567d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
5687551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
5697551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
570d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val bs = BitSet()
571d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            bs.set(0, model.getInvalidateableFieldLimit())
572d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val fs = FlagSet(bs, mDirtyFlags.buckets.size())
573d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
574d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
575d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
5765bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
5777551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
5787551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
579d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5800fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
582d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
5840fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
5865bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
58743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab ("case ${it.getName().br()} :") {
588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);")
589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
590d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
591d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
592d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
593d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
594d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5960fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
597d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
598d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
599d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareLog() = kcode("") {
6000fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("private void log(String msg, long i) {") {
601d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""")
6020fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        }
6030fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
604d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
605d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
606d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
6075bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filterNot{it.isUsed()}.forEach {
6085bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") {
6095bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
6105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
6115bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
6125bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
6135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
6145bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("return ${it.getDefaultValue()};")
6155bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
6165bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
6175bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
6185bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
61918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount            if (it.getUserDefinedType() != null) {
62018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") {
62118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
62218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                        tab("updateRegistration(${it.getId()}, ${it.readableUniqueName});");
62318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
62418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("this.${it.fieldName} = ${it.readableUniqueName};")
62518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
62618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
62718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    mDirtyFlags.mapOr(flagSet) { suffix, index ->
62818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                        tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
62918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
63018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
63218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
63318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
63418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
63518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
636d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
63718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
638d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
639d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
640d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
641d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
642d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
64334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
64434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
6454c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
646d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
647d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
648d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
649d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
650d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
651d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
652d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
653d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
654d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
65534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
65634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
657d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
658d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
65934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}, int fieldId) {") {
660d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
661d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
662d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    accessedFields.filter { it.canBeInvalidated() }
663d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
664d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
66543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
666d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
667d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
668d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                        tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
669d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    }
670d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
671d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
672d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
673d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
67443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
675d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
676d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
677d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
678d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
679d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
680d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
681d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
682d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
683d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
684d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
685d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
68634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
68734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
688d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
689d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
690d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
691d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
692dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
69396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getSortedTargets().filter {it.isUsed() && (oneLayout || it.getId() == null)}.forEach {
694dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
695dea555cf42dc3583604699c8c018d22681f56166George Mount            if (oneLayout && it.getId() != null) {
696dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
697dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
698dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
699dea555cf42dc3583604699c8c018d22681f56166George Mount            }
700dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${access} final ${it.interfaceType} ${it.fieldName};")
701d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
702d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
703d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
704d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
7055bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
7060fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
707d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
708d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
709d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
710d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
711d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
712de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
7130fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
714d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
715d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = ${longToBinary(value)};")
716d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
717d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
718d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
719d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
720d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
721d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
722d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
723d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
724d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
725d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
726d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
727d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
728d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
729d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
7310fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
7324c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("public void executePendingBindings() {") {
733d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
734d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
735d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
736d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
737d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${mDirtyFlags.localValue(i)} = 0;")
738d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
739d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            model.getPendingExpressions().filterNot {it.isVariable()}.forEach {
740d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${it.getResolvedType().toJavaCode()} ${it.localName} = ${it.getDefaultValue()};")
741d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
742d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
743d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
74474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
745d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val mJustRead = arrayListOf<Expr>()
746d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
7470fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    val readNow = batch.filter { it.shouldReadNow(mJustRead) }
748d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
749d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
750d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
75143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    Log.d { "new read now. batch size: ${batch.size()}, readNow size: ${readNow.size()}" }
752d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
753d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    readNow.forEach {
7540fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        nl(readWithDependants(it, mJustRead, batch, tmpDirtyFlags))
755d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
756d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    batch.removeAll(mJustRead)
757d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7580fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
759d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } while(model.markBitsRead())
760d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
761d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
76296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
763d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
764d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .groupBy { it.getExpr() }
765d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .forEach {
766d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.key.dirtyFlagSet
767d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
768d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
769d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }.joinToString(" || ")
770d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }) {") {
771d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
77297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                tab("// api target ${binding.getMinApi()}")
77334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val fieldName : String
77434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                if (binding.getTarget().getViewClass().
77534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                        equals(binding.getTarget().getInterfaceType())) {
77634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "this.${binding.getTarget().fieldName}"
77734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
77834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "((${binding.getTarget().getViewClass()}) this.${binding.getTarget().fieldName})"
77934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
78034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val bindingCode = binding.toJavaCode(fieldName, binding.getExpr().toCode().generate())
78197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                if (binding.getMinApi() > 1) {
7824c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                                    tab("if(getBuildSdkInt() >= ${binding.getMinApi()}) {") {
78397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                        tab("$bindingCode;")
78497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    }
78597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("}")
78697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                } else {
78797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("$bindingCode;")
78897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                }
789d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
790d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
791d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("}")
792d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
7935bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
7944c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
7957551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
79696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{
797de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                it.isUsed() && it.getResolvedType() != null && it.getResolvedType().extendsViewStub()
798de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }.forEach {
799de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("if (${it.fieldName}.getBinding() != null) {") {
800de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("${it.fieldName}.getBinding().executePendingBindings();")
801de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
802de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("}")
803de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
804d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
8050fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
806d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
807d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
808d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    fun readWithDependants(expr : Expr, mJustRead : MutableList<Expr>, batch : MutableList<Expr>,
809d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tmpDirtyFlags : FlagSet, inheritedFlags : FlagSet? = null) : KCode = kcode("") {
810d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mJustRead.add(expr)
81143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Log.d { expr.getUniqueKey() }
812d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val flagSet = expr.shouldReadFlagSet
813d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
814d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
81543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
81643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.joinToString(" || ")
817d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        })"
818d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
819d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val readCode = kcode("") {
820d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (!expr.isVariable()) {
821d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // it is not a variable read it.
822d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("// read ${expr.getUniqueKey()}")
823d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // create an if case for all dependencies that might be null
824d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val nullables = expr.getDependencies().filter {
825e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount                    it.isMandatory() && it.getOther().getResolvedType().isNullable()
82674f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                }.map { it.getOther() }
827d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
828d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab ("if ( ${nullables.map { "${it.localName} != null" }.joinToString(" && ")}) {") {
829d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";")
830d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
831d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("}")
832d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                } else {
833d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";")
834d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8357920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                if (expr.isObservable()) {
836d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("updateRegistration(${expr.getId()}, ${expr.localName});")
837d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8380fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            }
839d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
8400fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            // if I am the condition for an expression, set its flag
8410fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            val conditionals = expr.getDependants().filter { !it.isConditional()
8420fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    && it.getDependant() is TernaryExpr && (it.getDependant() as TernaryExpr).getPred() == expr }
8430fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    .map { it.getDependant() }
8440fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            if (conditionals.isNotEmpty()) {
8450fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// setting conditional flags")
8460fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("if (${expr.localName}) {") {
8470fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8480fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(true)
8490fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8500fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
851d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
852d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
853d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8540fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("} else {") {
8550fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8560fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(false)
8570fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8580fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
8590fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
8600fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
8610fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                } tab("}")
862d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
8630fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
864d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val chosen = expr.getDependants().filter {
865d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val dependant = it.getDependant()
866d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                batch.contains(dependant) &&
867d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadFlagSet.andNot(flagSet).isEmpty() &&
868d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadNow(mJustRead)
869d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
870d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (chosen.isNotEmpty()) {
871d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
872d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                chosen.forEach {
873d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                    nl(readWithDependants(it.getDependant(), mJustRead, batch, tmpDirtyFlags, nextInheritedFlags))
874d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
875d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
876d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
877d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (needsIfWrapper) {
878d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab(ifClause) {
879d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" {")
880d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                nl(readCode)
881d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
882d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab("}")
883d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
884d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            nl(readCode)
885d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
886d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
88743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
888dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
88996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (!layoutBinder.isMerge()) {
89096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} inflate(android.view.ViewGroup root) {") {
89196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("return bind(android.view.LayoutInflater.from(root.getContext()).inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true));")
892dea555cf42dc3583604699c8c018d22681f56166George Mount            }
89396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
89496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} inflate(android.content.Context context) {") {
89596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("return bind(android.view.LayoutInflater.from(context).inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false));")
89696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
89796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
89896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} bind(android.view.View view) {") {
89996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("if (!\"${layoutBinder.getTag()}_0\".equals(view.getTag())) {") {
90096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("throw new RuntimeException(\"view tag isn't correct on view\");")
90196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
90296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("}")
90396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("return new ${baseClassName}(view);")
90496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
90596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
906dea555cf42dc3583604699c8c018d22681f56166George Mount        }
907dea555cf42dc3583604699c8c018d22681f56166George Mount    }
908dea555cf42dc3583604699c8c018d22681f56166George Mount
9094c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public fun writeBaseClass() : String =
91043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
911fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
912fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
913fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
9144c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
91596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
916de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("public final ${it.interfaceType} ${it.fieldName};")
91734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
91834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
91934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab("protected ${baseClassName}(android.view.View root_, int localFieldCount") {
92096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
921de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab(", ${it.interfaceType} ${it.readableUniqueName}")
92234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
92334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
92434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
92534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                tab("super(root_, localFieldCount);")
92696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
92734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("this.${it.fieldName} = ${it.readableUniqueName};")
92834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
9294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9314c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
93243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
93318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
934895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    //it.getExpandedUserDefinedType(ModelAnalyzer.getInstance());
935895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
9364c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                    tab("public abstract void ${it.setterName}(${type} ${it.readableUniqueName});")
93718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
93843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
9394c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} inflate(android.view.ViewGroup root) {") {
940a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return DataBindingUtil.<${baseClassName}>inflate(root.getContext(), ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true);")
94143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
9424c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9434c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} inflate(android.content.Context context) {") {
944a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return DataBindingUtil.<${baseClassName}>inflate(context, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false);")
9454c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9464c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9474c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
948a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return (${baseClassName})DataBindingUtil.bindTo(view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
9494c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9504c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
95143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
95243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
953dea555cf42dc3583604699c8c018d22681f56166George Mount}
954