LayoutBinderWriter.kt revision 7ff60c24c6de7ba0c674fe65a82ad4a88dab2e5d
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
4296e1c821dd446d1ed78f8ae61131550588f60a24George Mountimport java.util.ArrayList
4334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.HashMap
4443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]").map{ it.trim() }.joinToCamelCaseAsVar()
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val usedFieldNames = hashSetOf<String>()
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val localizedFlags = arrayListOf<FlagSet>()
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun localizeFlag(set : FlagSet, name:String) : FlagSet {
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        localizedFlags.add(set)
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val result = getUniqueFieldName(name)
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        set.setLocalName(result)
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return set
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun getUniqueFieldName(base : String) : String {
59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var candidate = base
60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var i = 0
61d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        while (usedFieldNames.contains(candidate)) {
62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            i ++
63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            candidate = base + i
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        usedFieldNames.add(candidate)
66d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return candidate
67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
70de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval ExprModel.ext by Delegates.lazy { target : ExprModel ->
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    ExprModelExt()
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.getUniqueFieldName(base : String) : String = ext.getUniqueFieldName(base)
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
78de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.readableUniqueName by Delegates.lazy { target: BindingTarget ->
7900da715547ee7d5d38a3b8576090ca427a94daa5George Mount    val variableName : String
8000da715547ee7d5d38a3b8576090ca427a94daa5George Mount    if (target.getId() == null) {
8196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        variableName = "boundView" + indexFromTag(target.getTag())
8200da715547ee7d5d38a3b8576090ca427a94daa5George Mount    } else {
8300da715547ee7d5d38a3b8576090ca427a94daa5George Mount        variableName = target.getId().androidId().stripNonJava()
8400da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
8500da715547ee7d5d38a3b8576090ca427a94daa5George Mount    target.getModel().ext.getUniqueFieldName(variableName)
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
877551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
88de38dd3ef0577d25b2d59863603abe5750d0c231George Mountfun BindingTarget.superConversion(variable : String) : String {
8996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    if (getResolvedType() != null && getResolvedType().extendsViewStub()) {
90de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "new android.databinding.ViewStubProxy((android.view.ViewStub) ${variable})"
91de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
92de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "(${interfaceType}) ${variable}"
93de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
94de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
95de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
96de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.fieldName by Delegates.lazy { target : BindingTarget ->
9734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    if (target.getFieldName() == null) {
9834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        if (target.getId() == null) {
9934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.setFieldName("m${target.readableUniqueName.capitalize()}")
10034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        } else {
10134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.androidId.stripNonJava();
10234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            target.setFieldName(target.readableUniqueName);
10334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
10434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
10534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    target.getFieldName();
106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
108de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.getterName by Delegates.lazy { target : BindingTarget ->
109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "get${target.readableUniqueName.capitalize()}"
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
112de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.androidId by Delegates.lazy { target : BindingTarget ->
11343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    "R.id.${target.getId().androidId()}"
114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
116de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.interfaceType by Delegates.lazy { target : BindingTarget ->
117de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    if (target.getResolvedType() != null && target.getResolvedType().extendsViewStub()) {
118de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        "android.databinding.ViewStubProxy"
119de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
120de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        target.getInterfaceType()
121de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
122de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
123de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
124de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableUniqueName by Delegates.lazy { expr : Expr ->
12543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    Log.d { "readableUniqueName for ${expr.getUniqueKey()}" }
126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val stripped = "${expr.getUniqueKey().stripNonJava()}"
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getModel().ext.getUniqueFieldName(stripped)
128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
130de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableName by Delegates.lazy { expr : Expr ->
131de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    Log.d { "readableUniqueName for ${expr.getUniqueKey()}" }
132de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "${expr.getUniqueKey().stripNonJava()}"
133de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
134de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
135de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.fieldName by Delegates.lazy { expr : Expr ->
136de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "m${expr.readableName.capitalize()}"
137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
139de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.hasFlag by Delegates.lazy { expr : Expr ->
140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    expr.getId() < expr.getModel().getInvalidateableFieldLimit()
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
143de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.localName by Delegates.lazy { expr : Expr ->
144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if(expr.isVariable()) expr.fieldName else "${expr.readableUniqueName}"
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
146d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
147de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.setterName by Delegates.lazy { expr : Expr ->
148de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "set${expr.readableName.capitalize()}"
149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
150d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
151de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.onChangeName by Delegates.lazy { expr : Expr ->
152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "onChange${expr.readableUniqueName.capitalize()}"
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
155de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.getterName by Delegates.lazy { expr : Expr ->
156de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    "get${expr.readableName.capitalize()}"
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
159de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagName by Delegates.lazy { expr : Expr ->
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}"
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
163de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.shouldReadFlagName by Delegates.lazy { expr : Expr ->
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlagRead${expr.readableUniqueName.capitalize()}"
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
167de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagName by Delegates.lazy { expr : Expr ->
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}Invalid"
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
171de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlagPrefix by Delegates.lazy { expr : Expr ->
172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    "sFlag${expr.readableUniqueName.capitalize()}Is"
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.toCode(full : Boolean = false) : KCode {
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val it = this
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    if (isDynamic() && !full) {
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return kcode(localName)
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return when (it) {
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is ComparisonExpr -> kcode("") {
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getLeft().toCode())
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(it.getOp())
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getRight().toCode())
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is FieldAccessExpr -> kcode("") {
188a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount            app("", it.getChild().toCode())
189e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount            if (it.getGetter().type == Callable.Type.FIELD) {
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(".", it.getGetter().name)
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } else {
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(".", it.getGetter().name).app("()")
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
195d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is GroupExpr -> kcode("(").app("", it.getWrapped().toCode()).app(")")
196d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is StaticIdentifierExpr -> kcode(it.getResolvedType().toJavaCode())
197d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is IdentifierExpr -> kcode(it.localName)
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is MathExpr -> kcode("") {
199d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getLeft().toCode())
200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(it.getOp())
201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getRight().toCode())
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is MethodCallExpr -> kcode("") {
204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getTarget().toCode())
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(".", it.getGetter().name)
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("(")
207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            var first = true
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            it.getArgs().forEach {
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                apps(if (first) "" else ",", it.toCode())
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                first = false
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(")")
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is SymbolExpr -> kcode(it.getText()) // TODO
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        is TernaryExpr -> kcode("") {
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("", it.getPred().toCode())
217d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app("?", it.getIfTrue().toCode())
218d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            app(":", it.getIfFalse().toCode())
219d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
220c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        is ResourceExpr -> kcode("") {
221c752a5f795baf6df435ef60881316cb748df407cGeorge Mount            app("", it.toJava())
222c752a5f795baf6df435ef60881316cb748df407cGeorge Mount        }
2235cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        is BracketExpr -> kcode("") {
2245cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            app("", it.getTarget().toCode())
2255cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            val bracketType = it.getAccessor();
2265cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            when (bracketType) {
2275cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.ARRAY -> {
2285cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("[", it.getArg().toCode())
2295cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("]")
2305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2315cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.LIST -> {
2325cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(".get(")
2335cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    if (it.argCastsInteger()) {
2345cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                        app("(Integer)")
2355cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    }
2365cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app("", it.getArg().toCode())
2375cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(")")
2385cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2395cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                BracketExpr.BracketAccessor.MAP -> {
2405cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(".get(", it.getArg().toCode())
2415cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    app(")")
2425cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                }
2435cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
2445cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
245e4b93061ac703e48fc2c9994c9059ed016f05559George Mount        is CastExpr -> kcode("") {
246e4b93061ac703e48fc2c9994c9059ed016f05559George Mount            app("(", it.getCastType())
247e4b93061ac703e48fc2c9994c9059ed016f05559George Mount            app(") ", it.getCastExpr().toCode())
248e4b93061ac703e48fc2c9994c9059ed016f05559George Mount        }
249d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else -> kcode("//NOT IMPLEMENTED YET")
250d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
251d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
252d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
253d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
254d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
256d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
257d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
258d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
259de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagSet by Delegates.lazy { expr : Expr ->
260d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
261d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
262d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
263de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagSet by Delegates.lazy { expr : Expr ->
264d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getId())
265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
266d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
267de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.shouldReadFlagSet by Delegates.lazy { expr : Expr ->
268d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
270d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
271de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlags by Delegates.lazy { expr : Expr ->
272d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
273d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
274d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
275d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
276d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
278d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
279d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
280d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
281d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
282d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
283d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
284d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
285d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
286d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getBitSuffix(bitIndex : Int) : String {
287d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val word = bitIndex / FlagSet.sBucketSize
288d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return getWordSuffix(word)
289d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
290d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
291d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
293d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
294d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
295d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
296d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (getLocalName() == null) binaryCode(bucketIndex)
297d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
298d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
299d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
300d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
301d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
302d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun longToBinary(l : Long) =
303d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        "0b${java.lang.Long.toBinaryString(l)}L"
304d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
305d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
306d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
307d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
308d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
309d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
310d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
311d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
312d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
313d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
314d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
315d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
316d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
31796e1c821dd446d1ed78f8ae61131550588f60a24George Mountfun indexFromTag(tag : String) : kotlin.Int {
31896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    val startIndex : kotlin.Int
3197ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    if (tag.startsWith("binding_")) {
3207ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        startIndex = "binding_".length();
32196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    } else {
32296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        startIndex = tag.lastIndexOf('_') + 1
32396e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
32496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    return Integer.parseInt(tag.substring(startIndex))
32596e1c821dd446d1ed78f8ae61131550588f60a24George Mount}
32696e1c821dd446d1ed78f8ae61131550588f60a24George Mount
32743596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
328d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
32934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
33043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
33143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
33243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
33343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
33443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
33543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
336d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
337d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
33843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
339dea555cf42dc3583604699c8c018d22681f56166George Mount    val className = layoutBinder.getImplementationName()
340d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
34143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val identifiers by Delegates.lazy {
34243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        dynamics.filter { it is IdentifierExpr }
34343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
344d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
345dea555cf42dc3583604699c8c018d22681f56166George Mount    val baseClassName = "${layoutBinder.getClassName()}"
346d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3477551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
3487551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
3497551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
3507551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
35143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
35243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
35343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
354d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
3555bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
3565bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
3575bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
358d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
35996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public fun write(minSdk : kotlin.Int) : String  {
3605bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
36134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
3625bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
363a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
364a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
3655bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
366dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
367dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
368dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends ${baseClassName}"
369dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
370dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends android.databinding.ViewDataBinding"
371dea555cf42dc3583604699c8c018d22681f56166George Mount            }
372dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public class ${classDeclaration} {") {
3734c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
3745bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
3755bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
37696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab(declareConstructor(minSdk))
3775bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
3785bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
3795bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
3805bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
3815bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3825bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3834c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3845bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3855bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
386dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
387dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
388dea555cf42dc3583604699c8c018d22681f56166George Mount                }
3895bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3905bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3915bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3925bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3935bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
39534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
39696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getBindingTargets().filter{
39796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && it.getTag() != null && !it.isBinder()
39834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
39996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        taggedViews.forEach {
40096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it, indexFromTag(it.getTag()))
40196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
40296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val indexStart = maxIndex() + 1
40396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getBindingTargets().filter{
40496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && !taggedViews.contains(it)
40596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }.withIndex().forEach {
40696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it.value, it.index + indexStart)
40734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
40834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
4094c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
41096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        nl("private static final android.databinding.ViewDataBinding.IncludedLayoutIndex[][] sIncludes;")
4114c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
4124c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
4134c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
4144c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
4154c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
41600da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
41796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val numBindings = layoutBinder.getBindingTargets().filter{ it.isUsed() }.count()
41896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("sIncludes = new android.databinding.ViewDataBinding.IncludedLayoutIndex[${numBindings}][];")
41996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
42096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder() }.forEach {
42196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val includeTag = it.getTag();
42296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val parent = layoutBinder.getBindingTargets().firstOrNull {
42396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        it.isUsed() && !it.isBinder() && includeTag.equals(it.getTag())
42496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
42596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (parent == null) {
42696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        throw IllegalStateException("Could not find parent of include file")
42796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
42896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    var list = includeMap.get(parent)
42996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (list == null) {
43096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        list = ArrayList<BindingTarget>()
43196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.put(parent, list)
43296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
43396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    list.add(it)
4344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
43596e1c821dd446d1ed78f8ae61131550588f60a24George Mount
43696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                includeMap.keySet().forEach {
43796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val index = indices.get(it)
43896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("sIncludes[${index}] = new android.databinding.ViewDataBinding.IncludedLayoutIndex[] {") {
43996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.get(it).forEach {
44096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            val bindingIndex = indices.get(it)
44196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            val layoutName = it.getIncludedLayout()
44296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            tab("new android.databinding.ViewDataBinding.IncludedLayoutIndex(\"${layoutName}\", ${bindingIndex}, R.layout.${layoutName}),")
44396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        }
44496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
44596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("};")
44696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
44796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
44896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val viewsWithIds = layoutBinder.getBindingTargets().filter {
44996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                it.isUsed() && !it.isBinder() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
45000da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
45196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (viewsWithIds.isEmpty()) {
4524c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
45300da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
4544c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
45596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                viewsWithIds.forEach {
45634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sViewsWithIds.put(${it.androidId}, ${indices.get(it)});")
4574c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
45800da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
4594c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
4604c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
4614c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
46296e1c821dd446d1ed78f8ae61131550588f60a24George Mount
46396e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun maxIndex() : kotlin.Int {
46496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val maxIndex = indices.values().max()
46596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (maxIndex == null) {
46696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return -1
46796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
46896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return maxIndex
46996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
47096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
47196e1c821dd446d1ed78f8ae61131550588f60a24George Mount
47296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun declareConstructor(minSdk : kotlin.Int) = kcode("") {
47396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val bindingCount = maxIndex() + 1
47496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val parameterType : String
47596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val superParam : String
47696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (layoutBinder.isMerge()) {
47796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View[]"
47896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root[0]"
47996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
48096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View"
48196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root"
48296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
48396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val rootTagsSupported = minSdk >= 14
484dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
485dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
48696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public ${className}(${parameterType} root) {") {
48796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("this(${superParam}, mapBindings(root, ${bindingCount}, sIncludes, sViewsWithIds));")
488dea555cf42dc3583604699c8c018d22681f56166George Mount            }
489dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
49096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("private ${className}(${parameterType} root, Object[] bindings) {") {
49196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("super(${superParam}, ${model.getObservables().size()}") {
49296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    layoutBinder.getSortedTargets().filter { it.getId() != null }.forEach {
493dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
49434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
495dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
49634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
49734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
498dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
49996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public ${baseClassName}(${parameterType} root) {") {
50096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("super(${superParam}, ${model.getObservables().size()});")
50196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("final Object[] bindings = mapBindings(root, ${bindingCount}, sIncludes, sViewsWithIds);")
502dea555cf42dc3583604699c8c018d22681f56166George Mount            }
503dea555cf42dc3583604699c8c018d22681f56166George Mount        }
50496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        tab("setRootTag(root);")
50596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getSortedTargets().filter{it.isUsed()}
506dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
507dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!layoutBinder.hasVariations() || it.getId() == null) {
508dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
509dea555cf42dc3583604699c8c018d22681f56166George Mount            }
510dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!it.isBinder()) {
511de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                if (it.getResolvedType() != null && it.getResolvedType().extendsViewStub()) {
512de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
513de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
51496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (it.supportsTag() && it.getTag() != null &&
5157ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        (rootTagsSupported || it.getTag().startsWith("binding_"))) {
516dea555cf42dc3583604699c8c018d22681f56166George Mount                    val originalTag = it.getOriginalTag();
517dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
518dea555cf42dc3583604699c8c018d22681f56166George Mount                    if (originalTag != null) {
519dea555cf42dc3583604699c8c018d22681f56166George Mount                        tagValue = "\"${originalTag}\""
520dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
521dea555cf42dc3583604699c8c018d22681f56166George Mount                            var packageName = layoutBinder.getModulePackage()
522dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
523dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
52400da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
525dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
526dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
527dea555cf42dc3583604699c8c018d22681f56166George Mount                            tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
52800da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
52900da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
530dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab("this.${it.fieldName}.setTag(${tagValue});")
5317551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
532d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
533d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
534dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
5350fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
536d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
537d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
538dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
539dea555cf42dc3583604699c8c018d22681f56166George Mount        if (!target.isUsed()) {
540dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
541dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
54296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val index = indices.get(target)
543dea555cf42dc3583604699c8c018d22681f56166George Mount            if (index == null) {
54496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                throw IllegalStateException("Unknown binding target")
545dea555cf42dc3583604699c8c018d22681f56166George Mount            }
54696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val variableName = "bindings[${index}]"
547dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
548dea555cf42dc3583604699c8c018d22681f56166George Mount        }
549dea555cf42dc3583604699c8c018d22681f56166George Mount    }
550dea555cf42dc3583604699c8c018d22681f56166George Mount
551d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
5527551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
5537551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
554d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val bs = BitSet()
555d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            bs.set(0, model.getInvalidateableFieldLimit())
556d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val fs = FlagSet(bs, mDirtyFlags.buckets.size())
557d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
558d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
559d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
5605bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
5617551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
5627551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
563d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5640fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
565d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
566d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
567d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
5680fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
569d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
5705bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
57143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab ("case ${it.getName().br()} :") {
572d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);")
573d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
574d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
575d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
576d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
577d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
578d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
579d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5800fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
582d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareLog() = kcode("") {
5840fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("private void log(String msg, long i) {") {
585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""")
5860fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        }
5870fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
590d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
5915bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filterNot{it.isUsed()}.forEach {
5925bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") {
5935bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
5945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5955bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5965bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
5975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
5985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("return ${it.getDefaultValue()};")
5995bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
6005bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
6015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
6025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
60318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount            if (it.getUserDefinedType() != null) {
60418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") {
60518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
60618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                        tab("updateRegistration(${it.getId()}, ${it.readableUniqueName});");
60718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
60818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("this.${it.fieldName} = ${it.readableUniqueName};")
60918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
61018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
61118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    mDirtyFlags.mapOr(flagSet) { suffix, index ->
61218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                        tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
61318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
61418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
615d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
61618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
61718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
61818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
61918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
620d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
62118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
622d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
623d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
624d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
625d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
626d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
62734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
62834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
6294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
630d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
632d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
633d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
634d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
635d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
636d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
637d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
638d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
63934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
64034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
641d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
642d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
64334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}, int fieldId) {") {
644d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
645d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
646d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    accessedFields.filter { it.canBeInvalidated() }
647d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
648d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
64943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
650d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
651d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
652d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                        tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
653d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    }
654d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
655d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
656d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
657d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
65843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
659d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
660d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
661d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
662d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
663d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
664d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
665d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
666d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
667d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
668d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
669d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
67034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
67134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
672d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
673d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
674d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
675d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
676dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
67796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getSortedTargets().filter {it.isUsed() && (oneLayout || it.getId() == null)}.forEach {
678dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
679dea555cf42dc3583604699c8c018d22681f56166George Mount            if (oneLayout && it.getId() != null) {
680dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
681dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
682dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
683dea555cf42dc3583604699c8c018d22681f56166George Mount            }
684dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${access} final ${it.interfaceType} ${it.fieldName};")
685d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
686d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
687d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
688d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
6895bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
6900fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
691d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
692d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
693d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
694d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
695d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
696de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
6970fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
698d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
699d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = ${longToBinary(value)};")
700d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
701d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
702d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
703d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
704d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
705d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
706d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
707d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
708d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
709d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
710d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
711d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
712d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
713d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7144c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
7150fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
7164c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("public void executePendingBindings() {") {
717d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
718d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
719d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
720d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
721d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${mDirtyFlags.localValue(i)} = 0;")
722d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
723d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            model.getPendingExpressions().filterNot {it.isVariable()}.forEach {
724d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("${it.getResolvedType().toJavaCode()} ${it.localName} = ${it.getDefaultValue()};")
725d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
726d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
727d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
72874f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
729d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val mJustRead = arrayListOf<Expr>()
730d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
7310fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    val readNow = batch.filter { it.shouldReadNow(mJustRead) }
732d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
733d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
734d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
73543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    Log.d { "new read now. batch size: ${batch.size()}, readNow size: ${readNow.size()}" }
736d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
737d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    readNow.forEach {
7380fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        nl(readWithDependants(it, mJustRead, batch, tmpDirtyFlags))
739d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
740d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    batch.removeAll(mJustRead)
741d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7420fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
743d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } while(model.markBitsRead())
744d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
745d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
74696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
747d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
748d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .groupBy { it.getExpr() }
749d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .forEach {
750d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.key.dirtyFlagSet
751d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
752d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
753d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }.joinToString(" || ")
754d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }) {") {
755d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
75697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                tab("// api target ${binding.getMinApi()}")
75734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val fieldName : String
75834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                if (binding.getTarget().getViewClass().
75934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                        equals(binding.getTarget().getInterfaceType())) {
76034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "this.${binding.getTarget().fieldName}"
76134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
76234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "((${binding.getTarget().getViewClass()}) this.${binding.getTarget().fieldName})"
76334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
76434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val bindingCode = binding.toJavaCode(fieldName, binding.getExpr().toCode().generate())
76597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                if (binding.getMinApi() > 1) {
7664c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                                    tab("if(getBuildSdkInt() >= ${binding.getMinApi()}) {") {
76797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                        tab("$bindingCode;")
76897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    }
76997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("}")
77097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                } else {
77197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("$bindingCode;")
77297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                }
773d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
774d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
775d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("}")
776d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
7775bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
7784c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
7797551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
78096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{
781de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                it.isUsed() && it.getResolvedType() != null && it.getResolvedType().extendsViewStub()
782de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }.forEach {
783de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("if (${it.fieldName}.getBinding() != null) {") {
784de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("${it.fieldName}.getBinding().executePendingBindings();")
785de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
786de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("}")
787de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
788d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
7890fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
790d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
791d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
792d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    fun readWithDependants(expr : Expr, mJustRead : MutableList<Expr>, batch : MutableList<Expr>,
793d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tmpDirtyFlags : FlagSet, inheritedFlags : FlagSet? = null) : KCode = kcode("") {
794d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mJustRead.add(expr)
79543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Log.d { expr.getUniqueKey() }
796d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val flagSet = expr.shouldReadFlagSet
797d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
798d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
79943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
80043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.joinToString(" || ")
801d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        })"
802d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
803d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val readCode = kcode("") {
804d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (!expr.isVariable()) {
805d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // it is not a variable read it.
806d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("// read ${expr.getUniqueKey()}")
807d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // create an if case for all dependencies that might be null
808d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val nullables = expr.getDependencies().filter {
809e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount                    it.isMandatory() && it.getOther().getResolvedType().isNullable()
81074f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                }.map { it.getOther() }
811d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
812d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab ("if ( ${nullables.map { "${it.localName} != null" }.joinToString(" && ")}) {") {
813d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";")
814d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
815d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("}")
816d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                } else {
817d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";")
818d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8197920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                if (expr.isObservable()) {
820d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("updateRegistration(${expr.getId()}, ${expr.localName});")
821d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8220fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            }
823d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
8240fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            // if I am the condition for an expression, set its flag
8250fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            val conditionals = expr.getDependants().filter { !it.isConditional()
8260fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    && it.getDependant() is TernaryExpr && (it.getDependant() as TernaryExpr).getPred() == expr }
8270fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    .map { it.getDependant() }
8280fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            if (conditionals.isNotEmpty()) {
8290fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// setting conditional flags")
8300fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("if (${expr.localName}) {") {
8310fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8320fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(true)
8330fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8340fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
835d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
836d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
837d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8380fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("} else {") {
8390fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8400fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(false)
8410fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8420fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
8430fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
8440fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
8450fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                } tab("}")
846d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
8470fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
848d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val chosen = expr.getDependants().filter {
849d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val dependant = it.getDependant()
850d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                batch.contains(dependant) &&
851d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadFlagSet.andNot(flagSet).isEmpty() &&
852d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadNow(mJustRead)
853d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
854d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (chosen.isNotEmpty()) {
855d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
856d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                chosen.forEach {
857d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                    nl(readWithDependants(it.getDependant(), mJustRead, batch, tmpDirtyFlags, nextInheritedFlags))
858d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
859d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
860d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
861d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (needsIfWrapper) {
862d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab(ifClause) {
863d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" {")
864d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                nl(readCode)
865d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
866d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab("}")
867d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
868d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            nl(readCode)
869d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
870d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
87143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
872dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
87396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (!layoutBinder.isMerge()) {
87496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} inflate(android.view.ViewGroup root) {") {
87596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("return bind(android.view.LayoutInflater.from(root.getContext()).inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true));")
876dea555cf42dc3583604699c8c018d22681f56166George Mount            }
87796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
87896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} inflate(android.content.Context context) {") {
87996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("return bind(android.view.LayoutInflater.from(context).inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false));")
88096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
88196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
88296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} bind(android.view.View view) {") {
88396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("if (!\"${layoutBinder.getTag()}_0\".equals(view.getTag())) {") {
88496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("throw new RuntimeException(\"view tag isn't correct on view\");")
88596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
88696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("}")
88796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("return new ${baseClassName}(view);")
88896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
88996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
890dea555cf42dc3583604699c8c018d22681f56166George Mount        }
891dea555cf42dc3583604699c8c018d22681f56166George Mount    }
892dea555cf42dc3583604699c8c018d22681f56166George Mount
8934c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public fun writeBaseClass() : String =
89443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
895fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
896fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
897fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
8984c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
89996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
900de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("public final ${it.interfaceType} ${it.fieldName};")
90134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
90234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
90334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab("protected ${baseClassName}(android.view.View root_, int localFieldCount") {
90496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
905de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab(", ${it.interfaceType} ${it.readableUniqueName}")
90634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
90734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
90834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
90934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                tab("super(root_, localFieldCount);")
91096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
91134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("this.${it.fieldName} = ${it.readableUniqueName};")
91234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
9134c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9144c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9154c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
91643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
91718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
918895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    //it.getExpandedUserDefinedType(ModelAnalyzer.getInstance());
919895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
9204c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                    tab("public abstract void ${it.setterName}(${type} ${it.readableUniqueName});")
92118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
92243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
9234c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} inflate(android.view.ViewGroup root) {") {
924a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return DataBindingUtil.<${baseClassName}>inflate(root.getContext(), ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true);")
92543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
9264c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9274c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} inflate(android.content.Context context) {") {
928a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return DataBindingUtil.<${baseClassName}>inflate(context, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false);")
9294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9314c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
932a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                tab("return (${baseClassName})DataBindingUtil.bindTo(view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
9334c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
93543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
93643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
937dea555cf42dc3583604699c8c018d22681f56166George Mount}
938