LayoutBinderWriter.kt revision d8c8ec27ed2ec0b11fa37f476395ce27834471f0
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
4234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.HashMap
4343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]").map{ it.trim() }.joinToCamelCaseAsVar()
45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val usedFieldNames = hashSetOf<String>()
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val localizedFlags = arrayListOf<FlagSet>()
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun localizeFlag(set : FlagSet, name:String) : FlagSet {
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        localizedFlags.add(set)
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val result = getUniqueFieldName(name)
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        set.setLocalName(result)
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return set
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun getUniqueFieldName(base : String) : String {
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var candidate = base
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var i = 0
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        while (usedFieldNames.contains(candidate)) {
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            i ++
62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            candidate = base + i
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        usedFieldNames.add(candidate)
65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return candidate
66d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
69de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval ExprModel.ext by Delegates.lazy { target : ExprModel ->
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    ExprModelExt()
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.getUniqueFieldName(base : String) : String = ext.getUniqueFieldName(base)
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
77de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.readableUniqueName by Delegates.lazy { target: BindingTarget ->
7800da715547ee7d5d38a3b8576090ca427a94daa5George Mount    val variableName : String
7900da715547ee7d5d38a3b8576090ca427a94daa5George Mount    if (target.getId() == null) {
8000da715547ee7d5d38a3b8576090ca427a94daa5George Mount        variableName = "boundView" + target.getTag()
8100da715547ee7d5d38a3b8576090ca427a94daa5George Mount    } else {
8200da715547ee7d5d38a3b8576090ca427a94daa5George Mount        variableName = target.getId().androidId().stripNonJava()
8300da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
8400da715547ee7d5d38a3b8576090ca427a94daa5George Mount    target.getModel().ext.getUniqueFieldName(variableName)
85d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
867551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
87de38dd3ef0577d25b2d59863603abe5750d0c231George Mountfun BindingTarget.superConversion(variable : String) : String {
88de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    if (isBinder()) {
89de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "${getViewClass()}.bind(${variable})"
90de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else if (getResolvedType() != null && getResolvedType().extendsViewStub()) {
91de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "new android.databinding.ViewStubProxy((android.view.ViewStub) ${variable})"
92de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
93de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "(${interfaceType}) ${variable}"
94de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
95de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
96de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
97de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.fieldName by Delegates.lazy { target : BindingTarget ->
9834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    if (target.getFieldName() == null) {
9934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        if (target.getId() == null) {
10034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.setFieldName("m${target.readableUniqueName.capitalize()}")
10134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        } else {
10234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.androidId.stripNonJava();
10334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.setFieldName(target.readableUniqueName);
10434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
10534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
10634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    target.getFieldName();
107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
109de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.getterName by Delegates.lazy { target : BindingTarget ->
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "get${target.readableUniqueName.capitalize()}"
111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
113de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.androidId by Delegates.lazy { target : BindingTarget ->
11443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    "R.id.${target.getId().androidId()}"
115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
116d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
117de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.interfaceType by Delegates.lazy { target : BindingTarget ->
118de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    if (target.getResolvedType() != null && target.getResolvedType().extendsViewStub()) {
119de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        "android.databinding.ViewStubProxy"
120de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
121de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        target.getInterfaceType()
122de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
123de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
124de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
125de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableUniqueName by Delegates.lazy { expr : Expr ->
12643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    Log.d { "readableUniqueName for ${expr.getUniqueKey()}" }
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val stripped = "${expr.getUniqueKey().stripNonJava()}"
128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getModel().ext.getUniqueFieldName(stripped)
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
131de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableName by Delegates.lazy { expr : Expr ->
132de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    Log.d { "readableUniqueName for ${expr.getUniqueKey()}" }
133de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "${expr.getUniqueKey().stripNonJava()}"
134de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
135de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
136de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.fieldName by Delegates.lazy { expr : Expr ->
137de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "m${expr.readableName.capitalize()}"
138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
139d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
140de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.hasFlag by Delegates.lazy { expr : Expr ->
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getId() < expr.getModel().getInvalidateableFieldLimit()
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
144de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.localName by Delegates.lazy { expr : Expr ->
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if(expr.isVariable()) expr.fieldName else "${expr.readableUniqueName}"
146d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
147d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
148de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.setterName by Delegates.lazy { expr : Expr ->
149de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "set${expr.readableName.capitalize()}"
150d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
151d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
152de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.onChangeName by Delegates.lazy { expr : Expr ->
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "onChange${expr.readableUniqueName.capitalize()}"
154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
156de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.getterName by Delegates.lazy { expr : Expr ->
157de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "get${expr.readableName.capitalize()}"
158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
160de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagName by Delegates.lazy { expr : Expr ->
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}"
162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
164de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.shouldReadFlagName by Delegates.lazy { expr : Expr ->
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlagRead${expr.readableUniqueName.capitalize()}"
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
167d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
168de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagName by Delegates.lazy { expr : Expr ->
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}Invalid"
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
171d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
172de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlagPrefix by Delegates.lazy { expr : Expr ->
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}Is"
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.toCode(full : Boolean = false) : KCode {
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val it = this
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if (isDynamic() && !full) {
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return kcode(localName)
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return when (it) {
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is ComparisonExpr -> kcode("") {
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getLeft().toCode())
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(it.getOp())
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getRight().toCode())
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is FieldAccessExpr -> kcode("") {
189a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount            app("", it.getChild().toCode())
190e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount            if (it.getGetter().type == Callable.Type.FIELD) {
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(".", it.getGetter().name)
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } else {
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(".", it.getGetter().name).app("()")
194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
195d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
196d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is GroupExpr -> kcode("(").app("", it.getWrapped().toCode()).app(")")
197d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is StaticIdentifierExpr -> kcode(it.getResolvedType().toJavaCode())
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is IdentifierExpr -> kcode(it.localName)
199d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is MathExpr -> kcode("") {
200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getLeft().toCode())
201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(it.getOp())
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getRight().toCode())
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is MethodCallExpr -> kcode("") {
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getTarget().toCode())
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(".", it.getGetter().name)
207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("(")
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            var first = true
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            it.getArgs().forEach {
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                apps(if (first) "" else ",", it.toCode())
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                first = false
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(")")
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is SymbolExpr -> kcode(it.getText()) // TODO
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is TernaryExpr -> kcode("") {
217d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getPred().toCode())
218d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("?", it.getIfTrue().toCode())
219d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(":", it.getIfFalse().toCode())
220d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
221c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        is ResourceExpr -> kcode("") {
222c752a5f795baf6df435ef60881316cb748df407cGeorge Mount            app("", it.toJava())
223c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        }
2245cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        is BracketExpr -> kcode("") {
2255cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            app("", it.getTarget().toCode())
2265cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            val bracketType = it.getAccessor();
2275cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            when (bracketType) {
2285cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.ARRAY -> {
2295cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("[", it.getArg().toCode())
2305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("]")
2315cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2325cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.LIST -> {
2335cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(".get(")
2345cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    if (it.argCastsInteger()) {
2355cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                        app("(Integer)")
2365cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    }
2375cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("", it.getArg().toCode())
2385cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(")")
2395cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2405cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.MAP -> {
2415cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(".get(", it.getArg().toCode())
2425cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(")")
2435cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2445cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
2455cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
246e4b93061ac703e48fc2c9994c9059ed016f05559George Mount        is CastExpr -> kcode("") {
247e4b93061ac703e48fc2c9994c9059ed016f05559George Mount            app("(", it.getCastType())
248e4b93061ac703e48fc2c9994c9059ed016f05559George Mount            app(") ", it.getCastExpr().toCode())
249e4b93061ac703e48fc2c9994c9059ed016f05559George Mount        }
250d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else -> kcode("//NOT IMPLEMENTED YET")
251d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
252d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
253d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
254d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
256d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
257d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
258d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
259d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
260de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagSet by Delegates.lazy { expr : Expr ->
261d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
262d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
263d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
264de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagSet by Delegates.lazy { expr : Expr ->
265d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getId())
266d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
268de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.shouldReadFlagSet by Delegates.lazy { expr : Expr ->
269d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
270d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
271d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
272de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlags by Delegates.lazy { expr : Expr ->
273d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
274d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
275d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
276d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
278d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
279d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
280d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
281d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
282d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
283d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
284d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
285d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
286d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
287d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getBitSuffix(bitIndex : Int) : String {
288d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val word = bitIndex / FlagSet.sBucketSize
289d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return getWordSuffix(word)
290d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
291d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
293d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
294d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
295d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
296d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
297d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (getLocalName() == null) binaryCode(bucketIndex)
298d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
299d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
300d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
301d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
302d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
303d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun longToBinary(l : Long) =
304d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        "0b${java.lang.Long.toBinaryString(l)}L"
305d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
306d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
307d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
308d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
309d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
310d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
311d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
312d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
313d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
314d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
315d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
316d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
317d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
31843596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
319d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
32034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
32143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
32243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
32343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
32443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
32543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
32643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
327d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
328d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
32943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
330dea555cf42dc3583604699c8c018d22681f56166George Mount    val className = layoutBinder.getImplementationName()
331d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
33243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val identifiers by Delegates.lazy {
33343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        dynamics.filter { it is IdentifierExpr }
33443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
335d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
336dea555cf42dc3583604699c8c018d22681f56166George Mount    val baseClassName = "${layoutBinder.getClassName()}"
337d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3387551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
3397551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
3407551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
3417551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
34243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
34343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
34443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
345d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3465bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
3475bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
3485bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
349d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3505bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    public fun write() : String  {
3515bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
35234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
3535bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
354a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
355a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
3565bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
357dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
358dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
359dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends ${baseClassName}"
360dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
361dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends android.databinding.ViewDataBinding"
362dea555cf42dc3583604699c8c018d22681f56166George Mount            }
363dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public class ${classDeclaration} {") {
3644c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
3655bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
3665bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
3675bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareConstructor())
3685bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
3695bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
3705bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
3715bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
3725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3735bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3744c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3755bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3765bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
377dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
378dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
379dea555cf42dc3583604699c8c018d22681f56166George Mount                }
3805bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3815bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3825bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3835bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3845bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3855bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
38634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
38734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        val numTaggedViews = layoutBinder.getBindingTargets().
38895d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount                filter{it.isUsed() && it.getTag() != null}.count()
38934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        layoutBinder.getBindingTargets().filter{ it.isUsed() && it.getTag() != null }.forEach {
39034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            indices.put(it, Integer.parseInt(it.getTag()));
39134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
39295d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount        layoutBinder.getBindingTargets().filter{ it.isUsed() && it.getTag() == null && it.getId() != null }.withIndex().forEach {
39334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            indices.put(it.value, it.index + numTaggedViews);
39434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
39534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
3964c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
3974c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sIncludes;")
3984c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
3994c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
4004c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
4014c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
4024c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
40300da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
4044c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = new android.util.SparseIntArray();")
40534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder()}.forEach {
40634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sIncludes.put(${it.androidId}, ${indices.get(it)});")
4074c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
40800da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
40995d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount            val hasViewsWithIds = layoutBinder.getBindingTargets().firstOrNull{
41095d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount                it.isUsed() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
41195d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount            } != null
4124c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasViewsWithIds) {
4134c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
41400da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
4154c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
41695d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount                layoutBinder.getBindingTargets().filter{
41795d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount                    it.isUsed() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
41895d1b38adeb5963ec5337e7dd6177b4bb5a03619George Mount                }.forEach {
41934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sViewsWithIds.put(${it.androidId}, ${indices.get(it)});")
4204c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
42100da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
4224c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
4234c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
4244c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
4254c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareConstructor() = kcode("") {
426dea555cf42dc3583604699c8c018d22681f56166George Mount        val viewCount = layoutBinder.getBindingTargets().filter{it.isUsed()}.count()
427dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
428dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
429dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public ${className}(View root) {") {
430dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this(root, mapChildViews(root, ${viewCount}, sIncludes, sViewsWithIds));")
431dea555cf42dc3583604699c8c018d22681f56166George Mount            }
432dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
433dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("private ${className}(View root, View[] views) {") {
434dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("super(root, ${model.getObservables().size()}") {
435dea555cf42dc3583604699c8c018d22681f56166George Mount                    layoutBinder.getBindingTargets().filter { it.getId() != null }.forEach {
436dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
43734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
438dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
43934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
44034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
441dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
442dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${baseClassName}(View root) {") {
443dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("super(root, ${model.getObservables().size()});")
444dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("final View[] views = mapChildViews(root, ${viewCount}, sIncludes, sViewsWithIds);")
445dea555cf42dc3583604699c8c018d22681f56166George Mount            }
446dea555cf42dc3583604699c8c018d22681f56166George Mount        }
447dea555cf42dc3583604699c8c018d22681f56166George Mount        val taggedViews = layoutBinder.getBindingTargets().filter{it.isUsed()}
448dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
449dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!layoutBinder.hasVariations() || it.getId() == null) {
450dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
451dea555cf42dc3583604699c8c018d22681f56166George Mount            }
452dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!it.isBinder()) {
453de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                if (it.getResolvedType() != null && it.getResolvedType().extendsViewStub()) {
454de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
455de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
456dea555cf42dc3583604699c8c018d22681f56166George Mount                if (it.supportsTag() && it.getTag() != null) {
457dea555cf42dc3583604699c8c018d22681f56166George Mount                    val originalTag = it.getOriginalTag();
458dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
459dea555cf42dc3583604699c8c018d22681f56166George Mount                    if (originalTag != null) {
460dea555cf42dc3583604699c8c018d22681f56166George Mount                        tagValue = "\"${originalTag}\""
461dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
462dea555cf42dc3583604699c8c018d22681f56166George Mount                            var packageName = layoutBinder.getModulePackage()
463dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
464dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
46500da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
466dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
467dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
468dea555cf42dc3583604699c8c018d22681f56166George Mount                            tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
46900da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
47000da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
471dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab("this.${it.fieldName}.setTag(${tagValue});")
4727551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
473d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
474d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
475dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
4760fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
477d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
478d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
479dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
480dea555cf42dc3583604699c8c018d22681f56166George Mount        val index = indices.get(target)
481dea555cf42dc3583604699c8c018d22681f56166George Mount        if (!target.isUsed()) {
482dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
483dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
484dea555cf42dc3583604699c8c018d22681f56166George Mount            val variableName: String
485dea555cf42dc3583604699c8c018d22681f56166George Mount            if (index == null) {
486dea555cf42dc3583604699c8c018d22681f56166George Mount                variableName = "root";
487dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
488dea555cf42dc3583604699c8c018d22681f56166George Mount                variableName = "views[${index}]"
489dea555cf42dc3583604699c8c018d22681f56166George Mount            }
490dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
491dea555cf42dc3583604699c8c018d22681f56166George Mount        }
492dea555cf42dc3583604699c8c018d22681f56166George Mount    }
493dea555cf42dc3583604699c8c018d22681f56166George Mount
494d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
4957551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
4967551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
497d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val bs = BitSet()
498d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            bs.set(0, model.getInvalidateableFieldLimit())
499d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val fs = FlagSet(bs, mDirtyFlags.buckets.size())
500d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
501d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
502d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
5035bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
5047551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
5057551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
506d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5070fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
508d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
509d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
510d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
5110fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
512d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
5135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
51443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab ("case ${it.getName().br()} :") {
515d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);")
516d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
517d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
518d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
519d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
520d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
521d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
522d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5230fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
524d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
525d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
526d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareLog() = kcode("") {
5270fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("private void log(String msg, long i) {") {
528d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""")
5290fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        }
5300fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
531d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
532d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
533d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
5345bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filterNot{it.isUsed()}.forEach {
5355bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") {
5365bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
5375bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5385bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5395bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
5405bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
5415bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("return ${it.getDefaultValue()};")
5425bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5435bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5445bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
5455bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
54618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount            if (it.getUserDefinedType() != null) {
54718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") {
54818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
54918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                        tab("updateRegistration(${it.getId()}, ${it.readableUniqueName});");
55018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
55118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("this.${it.fieldName} = ${it.readableUniqueName};")
55218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
55318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
55418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    mDirtyFlags.mapOr(flagSet) { suffix, index ->
55518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                        tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
55618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
55718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
558d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
55918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
56018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
56118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
56218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
563d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
56418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
565d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
566d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
567d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
568d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
569d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
57034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
57134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
5724c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
573d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
574d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
575d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
576d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
577d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
578d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
579d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
580d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
58234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
58334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
584d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
58634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}, int fieldId) {") {
587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    accessedFields.filter { it.canBeInvalidated() }
590d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
591d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
59243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
593d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
594d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                        tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
596d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    }
597d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
598d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
599d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
600d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
60143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
602d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
603d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
604d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
605d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
606d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
607d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
608d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
609d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
610d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
611d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
612d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
61334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
61434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
615d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
616d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
617d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
618d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
619dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
620dea555cf42dc3583604699c8c018d22681f56166George Mount        layoutBinder.getBindingTargets().filter {it.isUsed() && (oneLayout || it.getId() == null)}.forEach {
621dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
622dea555cf42dc3583604699c8c018d22681f56166George Mount            if (oneLayout && it.getId() != null) {
623dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
624dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
625dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
626dea555cf42dc3583604699c8c018d22681f56166George Mount            }
627dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${access} final ${it.interfaceType} ${it.fieldName};")
628d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
629d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
630d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
6325bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
6330fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
634d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
635d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
636d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
637d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
638d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
639de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
6400fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
641d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
642d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = ${longToBinary(value)};")
643d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
644d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
645d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
646d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
647d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
648d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
649d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
650d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
651d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
652d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
653d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
654d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
655d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
656d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
6574c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
6580fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
6594c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("public void executePendingBindings() {") {
660d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
661d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
662d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
663d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
664d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${mDirtyFlags.localValue(i)} = 0;")
665d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
666d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            model.getPendingExpressions().filterNot {it.isVariable()}.forEach {
667d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${it.getResolvedType().toJavaCode()} ${it.localName} = ${it.getDefaultValue()};")
668d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
669d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
670d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
67174f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
672d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val mJustRead = arrayListOf<Expr>()
673d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
6740fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    val readNow = batch.filter { it.shouldReadNow(mJustRead) }
675d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
676d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
677d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
67843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    Log.d { "new read now. batch size: ${batch.size()}, readNow size: ${readNow.size()}" }
679d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
680d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    readNow.forEach {
6810fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        nl(readWithDependants(it, mJustRead, batch, tmpDirtyFlags))
682d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
683d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    batch.removeAll(mJustRead)
684d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
6850fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
686d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } while(model.markBitsRead())
687d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
688d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
6895bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            layoutBinder.getBindingTargets().filter { it.isUsed() }
690d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
691d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .groupBy { it.getExpr() }
692d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .forEach {
693d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.key.dirtyFlagSet
694d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
695d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
696d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }.joinToString(" || ")
697d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }) {") {
698d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
69997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                tab("// api target ${binding.getMinApi()}")
70034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val fieldName : String
70134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                if (binding.getTarget().getViewClass().
70234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                        equals(binding.getTarget().getInterfaceType())) {
70334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "this.${binding.getTarget().fieldName}"
70434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
70534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "((${binding.getTarget().getViewClass()}) this.${binding.getTarget().fieldName})"
70634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
70734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val bindingCode = binding.toJavaCode(fieldName, binding.getExpr().toCode().generate())
70897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                if (binding.getMinApi() > 1) {
7094c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                                    tab("if(getBuildSdkInt() >= ${binding.getMinApi()}) {") {
71097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                        tab("$bindingCode;")
71197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    }
71297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("}")
71397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                } else {
71497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("$bindingCode;")
71597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                }
716d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
717d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
718d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("}")
719d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
7205bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
7214c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
7227551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
723de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            layoutBinder.getBindingTargets().filter{
724de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                it.isUsed() && it.getResolvedType() != null && it.getResolvedType().extendsViewStub()
725de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }.forEach {
726de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("if (${it.fieldName}.getBinding() != null) {") {
727de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("${it.fieldName}.getBinding().executePendingBindings();")
728de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
729de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("}")
730de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
731d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
7320fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
733d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
734d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
735d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    fun readWithDependants(expr : Expr, mJustRead : MutableList<Expr>, batch : MutableList<Expr>,
736d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tmpDirtyFlags : FlagSet, inheritedFlags : FlagSet? = null) : KCode = kcode("") {
737d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mJustRead.add(expr)
73843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Log.d { expr.getUniqueKey() }
739d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val flagSet = expr.shouldReadFlagSet
740d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
741d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
74243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
74343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.joinToString(" || ")
744d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        })"
745d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
746d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val readCode = kcode("") {
747d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (!expr.isVariable()) {
748d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // it is not a variable read it.
749d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("// read ${expr.getUniqueKey()}")
750d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // create an if case for all dependencies that might be null
751d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val nullables = expr.getDependencies().filter {
752e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount                    it.isMandatory() && it.getOther().getResolvedType().isNullable()
75374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                }.map { it.getOther() }
754d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
755d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab ("if ( ${nullables.map { "${it.localName} != null" }.joinToString(" && ")}) {") {
756d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";")
757d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
758d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("}")
759d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                } else {
760d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";")
761d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7627920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                if (expr.isObservable()) {
763d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("updateRegistration(${expr.getId()}, ${expr.localName});")
764d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7650fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            }
766d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7670fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            // if I am the condition for an expression, set its flag
7680fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            val conditionals = expr.getDependants().filter { !it.isConditional()
7690fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    && it.getDependant() is TernaryExpr && (it.getDependant() as TernaryExpr).getPred() == expr }
7700fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    .map { it.getDependant() }
7710fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            if (conditionals.isNotEmpty()) {
7720fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// setting conditional flags")
7730fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("if (${expr.localName}) {") {
7740fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
7750fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(true)
7760fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
7770fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
778d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
779d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
780d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7810fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("} else {") {
7820fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
7830fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(false)
7840fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
7850fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
7860fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
7870fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
7880fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                } tab("}")
789d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
7900fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
791d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val chosen = expr.getDependants().filter {
792d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val dependant = it.getDependant()
793d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                batch.contains(dependant) &&
794d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadFlagSet.andNot(flagSet).isEmpty() &&
795d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadNow(mJustRead)
796d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
797d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (chosen.isNotEmpty()) {
798d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
799d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                chosen.forEach {
800d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                    nl(readWithDependants(it.getDependant(), mJustRead, batch, tmpDirtyFlags, nextInheritedFlags))
801d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
802d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
803d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
804d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (needsIfWrapper) {
805d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab(ifClause) {
806d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" {")
807d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                nl(readCode)
808d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
809d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab("}")
810d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
811d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            nl(readCode)
812d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
813d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
81443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
815dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
816dea555cf42dc3583604699c8c018d22681f56166George Mount        nl("public static ${baseClassName} inflate(android.view.ViewGroup root) {") {
817dea555cf42dc3583604699c8c018d22681f56166George Mount            tab("return bind(android.view.LayoutInflater.from(root.getContext()).inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true));")
818dea555cf42dc3583604699c8c018d22681f56166George Mount        }
819dea555cf42dc3583604699c8c018d22681f56166George Mount        nl("}")
820dea555cf42dc3583604699c8c018d22681f56166George Mount        nl("public static ${baseClassName} inflate(android.content.Context context) {") {
821dea555cf42dc3583604699c8c018d22681f56166George Mount            tab("return bind(android.view.LayoutInflater.from(context).inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false));")
822dea555cf42dc3583604699c8c018d22681f56166George Mount        }
823dea555cf42dc3583604699c8c018d22681f56166George Mount        nl("}")
824dea555cf42dc3583604699c8c018d22681f56166George Mount        nl("public static ${baseClassName} bind(android.view.View view) {") {
825dea555cf42dc3583604699c8c018d22681f56166George Mount            tab("if (!\"${layoutBinder.getId()}\".equals(view.getTag())) {") {
826d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                tab("throw new RuntimeException(\"view tag isn't correct on view\");")
827dea555cf42dc3583604699c8c018d22681f56166George Mount            }
828dea555cf42dc3583604699c8c018d22681f56166George Mount            tab("}")
829dea555cf42dc3583604699c8c018d22681f56166George Mount            tab("return new ${baseClassName}(view);")
830dea555cf42dc3583604699c8c018d22681f56166George Mount        }
831dea555cf42dc3583604699c8c018d22681f56166George Mount        nl("}")
832dea555cf42dc3583604699c8c018d22681f56166George Mount    }
833dea555cf42dc3583604699c8c018d22681f56166George Mount
8344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public fun writeBaseClass() : String =
83543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
836fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
837fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
838fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
8394c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
84034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            layoutBinder.getBindingTargets().filter{it.getId() != null}.forEach {
841de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("public final ${it.interfaceType} ${it.fieldName};")
84234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
84334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
84434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab("protected ${baseClassName}(android.view.View root_, int localFieldCount") {
84534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                layoutBinder.getBindingTargets().filter{it.getId() != null}.forEach {
846de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab(", ${it.interfaceType} ${it.readableUniqueName}")
84734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
84834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
84934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
85034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                tab("super(root_, localFieldCount);")
85134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                layoutBinder.getBindingTargets().filter{it.getId() != null}.forEach {
85234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("this.${it.fieldName} = ${it.readableUniqueName};")
85334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
8544c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
8554c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
8564c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
85743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
85818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
859895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    //it.getExpandedUserDefinedType(ModelAnalyzer.getInstance());
860895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
8614c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                    tab("public abstract void ${it.setterName}(${type} ${it.readableUniqueName});")
86218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
86343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
8644c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} inflate(android.view.ViewGroup root) {") {
865a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return DataBindingUtil.<${baseClassName}>inflate(root.getContext(), ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true);")
86643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
8674c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
8684c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} inflate(android.content.Context context) {") {
869a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return DataBindingUtil.<${baseClassName}>inflate(context, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false);")
8704c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
8714c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
8724c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
873a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return (${baseClassName})DataBindingUtil.bindTo(view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
8744c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
8754c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
87643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
87743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
878dea555cf42dc3583604699c8c018d22681f56166George Mount}
879