LayoutBinderWriter.kt revision fead9ca09b117136b35bc5bf137340a754f9eddd
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
26fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.TernaryExpr
27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.FieldAccessExpr
28fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ComparisonExpr
29fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.GroupExpr
30fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.MathExpr
31fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.MethodCallExpr
32fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.StaticIdentifierExpr
33fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.SymbolExpr
34fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.androidId
35fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.lazy
36fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.ext.br
37fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ResourceExpr
38fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.BracketExpr
39fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.Callable
40fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.CastExpr
41fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer
4243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]").map{ it.trim() }.joinToCamelCaseAsVar()
44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val usedFieldNames = hashSetOf<String>()
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val localizedFlags = arrayListOf<FlagSet>()
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun localizeFlag(set : FlagSet, name:String) : FlagSet {
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        localizedFlags.add(set)
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val result = getUniqueFieldName(name)
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        set.setLocalName(result)
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return set
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun getUniqueFieldName(base : String) : String {
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var candidate = base
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var i = 0
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        while (usedFieldNames.contains(candidate)) {
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            i ++
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            candidate = base + i
62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        usedFieldNames.add(candidate)
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return candidate
65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
66d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval ExprModel.ext by Delegates.lazy { (target : ExprModel) ->
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    ExprModelExt()
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.getUniqueFieldName(base : String) : String = ext.getUniqueFieldName(base)
73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval BindingTarget.readableUniqueName by Delegates.lazy {(target: BindingTarget) ->
7700da715547ee7d5d38a3b8576090ca427a94daa5George Mount    val variableName : String
7800da715547ee7d5d38a3b8576090ca427a94daa5George Mount    if (target.getId() == null) {
7900da715547ee7d5d38a3b8576090ca427a94daa5George Mount        variableName = "boundView" + target.getTag()
8000da715547ee7d5d38a3b8576090ca427a94daa5George Mount    } else {
8100da715547ee7d5d38a3b8576090ca427a94daa5George Mount        variableName = target.getId().androidId().stripNonJava()
8200da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
8300da715547ee7d5d38a3b8576090ca427a94daa5George Mount    target.getModel().ext.getUniqueFieldName(variableName)
84d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
857551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval BindingTarget.fieldName by Delegates.lazy { (target : BindingTarget) ->
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "m${target.readableUniqueName.capitalize()}"
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval BindingTarget.getterName by Delegates.lazy { (target : BindingTarget) ->
91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "get${target.readableUniqueName.capitalize()}"
92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
94d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval BindingTarget.androidId by Delegates.lazy { (target : BindingTarget) ->
9543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    "R.id.${target.getId().androidId()}"
96d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.readableUniqueName by Delegates.lazy { (expr : Expr) ->
9943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    Log.d { "readableUniqueName for ${expr.getUniqueKey()}" }
100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val stripped = "${expr.getUniqueKey().stripNonJava()}"
101d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getModel().ext.getUniqueFieldName(stripped)
102d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
103d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.fieldName by Delegates.lazy { (expr : Expr) ->
105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "m${expr.readableUniqueName.capitalize()}"
106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.hasFlag by Delegates.lazy { (expr : Expr) ->
109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getId() < expr.getModel().getInvalidateableFieldLimit()
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.localName by Delegates.lazy { (expr : Expr) ->
113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if(expr.isVariable()) expr.fieldName else "${expr.readableUniqueName}"
114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
116d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.setterName by Delegates.lazy { (expr : Expr) ->
117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "set${expr.readableUniqueName.capitalize()}"
118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
119d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.onChangeName by Delegates.lazy { (expr : Expr) ->
121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "onChange${expr.readableUniqueName.capitalize()}"
122d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
123d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
124d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.getterName by Delegates.lazy { (expr : Expr) ->
125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "get${expr.readableUniqueName.capitalize()}"
126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.staticFieldName by Delegates.lazy { (expr : Expr) ->
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "s${expr.readableUniqueName.capitalize()}"
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.dirtyFlagName by Delegates.lazy { (expr : Expr) ->
133d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}"
134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
136d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.shouldReadFlagName by Delegates.lazy { (expr : Expr) ->
137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlagRead${expr.readableUniqueName.capitalize()}"
138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
139d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.invalidateFlagName by Delegates.lazy { (expr : Expr) ->
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}Invalid"
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.conditionalFlagPrefix by Delegates.lazy { (expr : Expr) ->
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}Is"
146d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
147d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
148d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.toCode(full : Boolean = false) : KCode {
150d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val it = this
151d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if (isDynamic() && !full) {
152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return kcode(localName)
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return when (it) {
155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is ComparisonExpr -> kcode("") {
156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getLeft().toCode())
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(it.getOp())
158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getRight().toCode())
159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is FieldAccessExpr -> kcode("") {
161a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount            app("", it.getChild().toCode())
162e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount            if (it.getGetter().type == Callable.Type.FIELD) {
163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(".", it.getGetter().name)
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } else {
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(".", it.getGetter().name).app("()")
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
167d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is GroupExpr -> kcode("(").app("", it.getWrapped().toCode()).app(")")
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is StaticIdentifierExpr -> kcode(it.getResolvedType().toJavaCode())
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is IdentifierExpr -> kcode(it.localName)
171d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is MathExpr -> kcode("") {
172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getLeft().toCode())
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(it.getOp())
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getRight().toCode())
175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is MethodCallExpr -> kcode("") {
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getTarget().toCode())
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(".", it.getGetter().name)
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("(")
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            var first = true
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            it.getArgs().forEach {
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                apps(if (first) "" else ",", it.toCode())
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                first = false
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(")")
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is SymbolExpr -> kcode(it.getText()) // TODO
188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is TernaryExpr -> kcode("") {
189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getPred().toCode())
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("?", it.getIfTrue().toCode())
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(":", it.getIfFalse().toCode())
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
193c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        is ResourceExpr -> kcode("") {
194c752a5f795baf6df435ef60881316cb748df407cGeorge Mount            app("", it.toJava())
195c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        }
1965cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        is BracketExpr -> kcode("") {
1975cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            app("", it.getTarget().toCode())
1985cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            val bracketType = it.getAccessor();
1995cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            when (bracketType) {
2005cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.ARRAY -> {
2015cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("[", it.getArg().toCode())
2025cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("]")
2035cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2045cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.LIST -> {
2055cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(".get(")
2065cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    if (it.argCastsInteger()) {
2075cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                        app("(Integer)")
2085cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    }
2095cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("", it.getArg().toCode())
2105cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(")")
2115cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2125cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.MAP -> {
2135cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(".get(", it.getArg().toCode())
2145cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(")")
2155cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2165cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
2175cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
218e4b93061ac703e48fc2c9994c9059ed016f05559George Mount        is CastExpr -> kcode("") {
219e4b93061ac703e48fc2c9994c9059ed016f05559George Mount            app("(", it.getCastType())
220e4b93061ac703e48fc2c9994c9059ed016f05559George Mount            app(") ", it.getCastExpr().toCode())
221e4b93061ac703e48fc2c9994c9059ed016f05559George Mount        }
222d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else -> kcode("//NOT IMPLEMENTED YET")
223d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
224d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
225d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
226d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
228d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.dirtyFlagSet by Delegates.lazy { (expr : Expr) ->
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val fs = FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getModel().localizeFlag(fs, expr.dirtyFlagName)
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.invalidateFlagSet by Delegates.lazy { (expr : Expr) ->
238d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val fs = FlagSet(expr.getId())
239d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getModel().localizeFlag(fs, expr.invalidateFlagName)
240d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
241d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
242d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.shouldReadFlagSet by Delegates.lazy { (expr : Expr) ->
243d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val fs = FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
244d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getModel().localizeFlag(fs, expr.shouldReadFlagName)
245d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
246d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
247d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarval Expr.conditionalFlags by Delegates.lazy { (expr : Expr) ->
248d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = expr.getModel()
249d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    arrayListOf(model.localizeFlag(FlagSet(expr.getRequirementFlagIndex(false)),
250d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            "${expr.conditionalFlagPrefix}False"),
251d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            model.localizeFlag(FlagSet(expr.getRequirementFlagIndex(true)),
252d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    "${expr.conditionalFlagPrefix}True"))
253d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
254d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
256d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
257d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
258d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
259d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
260d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
261d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
262d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
263d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
264d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getBitSuffix(bitIndex : Int) : String {
266d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val word = bitIndex / FlagSet.sBucketSize
267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return getWordSuffix(word)
268d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
270d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
271d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
272d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
273d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
274d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
275d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (getLocalName() == null) buckets[bucketIndex]
276d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
278d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.or(other : FlagSet, cb : (suffix : String) -> Unit) {
279d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
280d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
281d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
282d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
283d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(i))
284d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
285d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
286d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
287d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
288d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
289d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
290d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
291d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
293d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
294d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
295d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
296d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
297d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
298d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
299d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
30043596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
301d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
30243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
30343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
30443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
30543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
30643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
30743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
308d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
309d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
31043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
311d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val className = layoutBinder.getClassName()
312d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
31343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val identifiers by Delegates.lazy {
31443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        dynamics.filter { it is IdentifierExpr }
31543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
316d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3174c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    val baseClassName = "${layoutBinder.getInterfaceName()}"
318d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3197551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
3207551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
3217551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
3227551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
32343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
32443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
32543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
326d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3275bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
3285bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
3295bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
330d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3315bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    public fun write() : String  {
3325bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
3335bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
334a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
335a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
3365bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
3374c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public class ${className} extends ${baseClassName} {") {
3384c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
3395bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
3405bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
3415bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareConstructor())
3425bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
3435bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
3445bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
3455bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
3465bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(viewGetters())
3475bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3485bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3494c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3505bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3515bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
3525bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3535bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3545bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3555bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3565bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3575bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
3584c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
3594c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sIncludes;")
3604c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
3614c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
3624c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
3634c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
3644c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
36500da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
3664c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = new android.util.SparseIntArray();")
3674c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                val numTaggedViews = layoutBinder.getBindingTargets().
3684c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                        filter{it.isUsed() && !it.isBinder()}.count()
3694c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder()}.withIndex()
3704c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                        .forEach {
3714c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                    tab("sIncludes.put(${it.value.androidId}, ${it.index + numTaggedViews});")
3724c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
37300da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
3744c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasViewsWithIds = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && !it.supportsTag()} != null
3754c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasViewsWithIds) {
3764c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
37700da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
3784c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
3794c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && !it.supportsTag() }.
3804c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                        forEach {
3814c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                    tab("sViewsWithIds.put(${it.androidId}, ${it.getTag()});")
3824c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
38300da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
3844c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
3854c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
3864c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
3874c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareConstructor() = kcode("") {
3884c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("public ${className}(View root) {") {
3894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("super(root, ${model.getObservables().size()});")
3904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val viewCount = layoutBinder.getBindingTargets().filter{it.isUsed()}.count()
3914c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("View[] views = new View[${viewCount}];")
3924c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("mapTaggedChildViews(root, views, sIncludes, sViewsWithIds);");
3934c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val taggedViews = layoutBinder.getBindingTargets().filter{it.isUsed() && !it.isBinder()}
3944c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            taggedViews.forEach {
3954c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                if (it.getTag() == null) {
39600da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    tab("this.${it.fieldName} = (${it.getViewClass()}) root;")
3977551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                } else {
3984c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                    tab("this.${it.fieldName} = (${it.getViewClass()}) views[${it.getTag()}];")
39900da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    if (it.supportsTag()) {
40000da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        val originalTag = it.getOriginalTag();
40100da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        var tagValue = "null"
40200da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        if (originalTag != null) {
40300da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            tagValue = "\"${originalTag}\""
40400da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            if (originalTag.startsWith("@")) {
405a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                                var packageName = layoutBinder.getModulePackage()
40600da715547ee7d5d38a3b8576090ca427a94daa5George Mount                                if (originalTag.startsWith("@android:")) {
40700da715547ee7d5d38a3b8576090ca427a94daa5George Mount                                    packageName = "android"
40800da715547ee7d5d38a3b8576090ca427a94daa5George Mount                                }
40900da715547ee7d5d38a3b8576090ca427a94daa5George Mount                                val slashIndex = originalTag.indexOf('/')
41000da715547ee7d5d38a3b8576090ca427a94daa5George Mount                                val resourceId = originalTag.substring(slashIndex + 1)
41100da715547ee7d5d38a3b8576090ca427a94daa5George Mount                                tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
41200da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
41300da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
41400da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        tab("this.${it.fieldName}.setTag(${tagValue});")
41500da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
4167551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
417d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
4184c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val taggedCount = taggedViews.count()
4194c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            layoutBinder.getBindingTargets().filter{it.isUsed() && it.isBinder()}.withIndex()
4204c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                    .forEach {
4214c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("this.${it.value.fieldName} = ${it.value.getViewClass()}.bind(views[${it.index + taggedCount}]);")
4224c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
423d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("invalidateAll();");
424d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4250fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
426d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
427d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
428d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
4297551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
4307551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
431d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val bs = BitSet()
432d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            bs.set(0, model.getInvalidateableFieldLimit())
433d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val fs = FlagSet(bs, mDirtyFlags.buckets.size())
434d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
435d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
436d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
4375bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
4387551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
4397551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
440d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4410fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
442d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
443d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
444d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
4450fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
446d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
4475bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
44843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab ("case ${it.getName().br()} :") {
449d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);")
450d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
451d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
452d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
453d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
454d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
455d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
456d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4570fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
458d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
459d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
460d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareLog() = kcode("") {
4610fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("private void log(String msg, long i) {") {
462d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""")
4630fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        }
4640fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
465d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
466d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
467d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
4685bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filterNot{it.isUsed()}.forEach {
4695bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") {
4705bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
4715bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
4725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
4735bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
4745bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
4755bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("return ${it.getDefaultValue()};")
4765bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
4775bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
4785bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
4795bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
48018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount            if (it.getUserDefinedType() != null) {
48118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") {
48218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
48318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                        tab("updateRegistration(${it.getId()}, ${it.readableUniqueName});");
48418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
48518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("this.${it.fieldName} = ${it.readableUniqueName};")
48618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
48718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
48818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    mDirtyFlags.mapOr(flagSet) { suffix, index ->
48918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                        tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
49018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
49118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
492d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
49318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
49418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
49518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
49618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
497d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
49818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
499d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
500d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
501d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
502d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
503d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
504d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        tab("@Override")
5054c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        tab("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
5064c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
507d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
508d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
509d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
510d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
511d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
512d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
513d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
514d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
515d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
516d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        tab("}")
517d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
518d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
519d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}, int fieldId) {") {
520d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
521d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
522d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    accessedFields.filter { it.canBeInvalidated() }
523d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
524d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
52543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
526d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
527d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
528d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                        tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
529d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    }
530d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
531d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
532d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
533d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
53443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
535d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
536d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
537d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
538d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
539d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
540d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
541d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
542d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
543d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
544d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
545d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
546d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
547d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
548d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
549d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
550d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
5515bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.getBindingTargets().filter{it.isUsed()}.forEach {
55200da715547ee7d5d38a3b8576090ca427a94daa5George Mount            nl("private final ${it.getViewClass()} ${it.fieldName};")
553d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
554d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
555d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
556d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun viewGetters() = kcode("// view getters") {
55700da715547ee7d5d38a3b8576090ca427a94daa5George Mount        layoutBinder.getBindingTargets().filter{it.getId() != null}.forEach {
5580fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("@Override")
5595bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getInterfaceType()} ${it.getterName}() {") {
5605bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                if (it.isUsed()) {
5615bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                    tab("return ${it.fieldName};")
5625bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                } else {
5635bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                    tab("return null;")
5645bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                }
5655bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
566d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
5670fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("}")
568d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
569d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
570d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
571d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
5725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
5730fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
574d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
575d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
576d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
577d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
578d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
579d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            flag.notEmpty { (suffix, value) ->
5800fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
582d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = $value;")
583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
584d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
586d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
590d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
591d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
592d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
593d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
594d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
596d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
5974c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
5980fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
5994c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("public void executePendingBindings() {") {
600d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
601d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
602d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
603d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
604d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${mDirtyFlags.localValue(i)} = 0;")
605d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
6062c86cdbaf189e2b1774af7f64a2974de9321673fGeorge Mount            //tab("""log("dirty flags", mDirtyFlags);""")
607d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            model.getPendingExpressions().filterNot {it.isVariable()}.forEach {
608d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${it.getResolvedType().toJavaCode()} ${it.localName} = ${it.getDefaultValue()};")
609d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
610d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
611d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
612d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val batch = model.filterShouldRead(model.getPendingExpressions()).toArrayList()
613d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val mJustRead = arrayListOf<Expr>()
614d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
6150fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    val readNow = batch.filter { it.shouldReadNow(mJustRead) }
616d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
617d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
618d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
61943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    Log.d { "new read now. batch size: ${batch.size()}, readNow size: ${readNow.size()}" }
620d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
621d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    readNow.forEach {
6220fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        nl(readWithDependants(it, mJustRead, batch, tmpDirtyFlags))
623d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
624d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    batch.removeAll(mJustRead)
625d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
6260fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
627d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } while(model.markBitsRead())
628d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
629d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
6305bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            layoutBinder.getBindingTargets().filter { it.isUsed() }
631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
632d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .groupBy { it.getExpr() }
633d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .forEach {
634d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.key.dirtyFlagSet
635d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
636d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
637d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }.joinToString(" || ")
638d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }) {") {
639d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
64097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                tab("// api target ${binding.getMinApi()}")
64197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                val bindingCode = binding.toJavaCode(binding.getTarget().fieldName, binding.getExpr().toCode().generate())
64297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                if (binding.getMinApi() > 1) {
6434c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                                    tab("if(getBuildSdkInt() >= ${binding.getMinApi()}) {") {
64497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                        tab("$bindingCode;")
64597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    }
64697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("}")
64797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                } else {
64897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("$bindingCode;")
64997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                }
650d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
651d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
652d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("}")
653d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
6547551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            //
6555bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
6564c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
6577551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
658d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
6590fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
660d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
661d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
662d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun readWithDependants(expr : Expr, mJustRead : MutableList<Expr>, batch : MutableList<Expr>, tmpDirtyFlags : FlagSet) : KCode = kcode("") {
663d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mJustRead.add(expr)
66443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Log.d { expr.getUniqueKey() }
665d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val flagSet = expr.shouldReadFlagSet
666d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
66743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
66843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.joinToString(" || ")
669d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }) {") {
670d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (!expr.isVariable()) {
671d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // it is not a variable read it.
672d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("// read ${expr.getUniqueKey()}")
673d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // create an if case for all dependencies that might be null
674d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val nullables = expr.getDependencies().filter {
675e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount                    it.isMandatory() && it.getOther().getResolvedType().isNullable()
67643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                }
677d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        .map { it.getOther() }
678d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
679d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab ("if ( ${nullables.map { "${it.localName} != null" }.joinToString(" && ")}) {") {
680d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";")
6812c86cdbaf189e2b1774af7f64a2974de9321673fGeorge Mount                        //tab("""log("${expr}" + ${expr.localName},0);""")
682d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
683d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("}")
684d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                } else {
685d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";")
6862c86cdbaf189e2b1774af7f64a2974de9321673fGeorge Mount                    //tab("""log("${expr}" + ${expr.localName},0);""")
687d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
6887920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                if (expr.isObservable()) {
689d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("updateRegistration(${expr.getId()}, ${expr.localName});")
690d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
6910fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            }
692d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
6930fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            // if I am the condition for an expression, set its flag
6940fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            val conditionals = expr.getDependants().filter { !it.isConditional()
6950fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    && it.getDependant() is TernaryExpr && (it.getDependant() as TernaryExpr).getPred() == expr }
6960fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    .map { it.getDependant() }
6970fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            if (conditionals.isNotEmpty()) {
6980fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// setting conditional flags")
6990fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("if (${expr.localName}) {") {
7000fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
7010fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(true)
7020fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
7030fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
704d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
705d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
706d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7070fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("} else {") {
7080fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
7090fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(false)
7100fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
7110fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
7120fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
7130fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
7140fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                } tab("}")
715d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
7160fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
717d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val chosen = expr.getDependants().filter {
7180fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                batch.contains(it.getDependant()) && it.getDependant().shouldReadNow(mJustRead)
719d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
720d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (chosen.isNotEmpty()) {
721d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                chosen.forEach {
722d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    nl(readWithDependants(it.getDependant(), mJustRead, batch, tmpDirtyFlags))
723d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
724d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
725d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
726d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        tab("}")
727d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
72843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
7294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public fun writeBaseClass() : String =
73043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
731fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
732fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
733fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
7344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
7354c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("protected ${baseClassName}(android.view.View root, int localFieldCount) {") {
7364c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("super(root, localFieldCount);")
7374c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
7384c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
7394c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
74043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
74118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
74218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("@Bindable")
743895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    //it.getExpandedUserDefinedType(ModelAnalyzer.getInstance());
744895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
7454c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                    tab("public abstract void ${it.setterName}(${type} ${it.readableUniqueName});")
74618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
74743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
74800da715547ee7d5d38a3b8576090ca427a94daa5George Mount            layoutBinder.getBindingTargets().filter{ it.getId() != null }.forEach {
7494c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("public abstract ${it.getInterfaceType()} ${it.getterName}();")
7504c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
7514c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
7524c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} inflate(android.view.ViewGroup root) {") {
753a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return DataBindingUtil.<${baseClassName}>inflate(root.getContext(), ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true);")
75443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
7554c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
7564c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} inflate(android.content.Context context) {") {
757a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return DataBindingUtil.<${baseClassName}>inflate(context, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false);")
7584c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
7594c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
7604c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
761a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return (${baseClassName})DataBindingUtil.bindTo(view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
7624c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
7634c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
76443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
76543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
766d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}