LayoutBinderWriter.kt revision b1356339eaa6c8e967e4fc1dc283b82909a1208d
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
17e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport kotlin.properties.Delegates
18e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.BindingTarget
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.Expr
20d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport kotlin.properties.Delegates
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.BindingTarget
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.IdentifierExpr
23d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.BitSet
24fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ExprModel
25d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.Arrays
26c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.tool.expr.BitShiftExpr
27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.TernaryExpr
28fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.FieldAccessExpr
29fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ComparisonExpr
30fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.GroupExpr
31c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.tool.expr.InstanceOfExpr
32fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.MathExpr
33fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.MethodCallExpr
34fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.StaticIdentifierExpr
35fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.SymbolExpr
36c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mountimport android.databinding.tool.expr.UnaryExpr
37fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.ResourceExpr
38fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.expr.BracketExpr
39e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport android.databinding.tool.ext;
407b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.androidId
417b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.lazy
427b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.versionedLazy
437b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.br
447b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.ext.joinToCamelCaseAsVar
45e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport java.util.BitSet
46e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarimport java.util.Arrays
47fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.Callable
48fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer
497b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport android.databinding.tool.util.L
507b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport com.google.common.collect.Iterables
5196e1c821dd446d1ed78f8ae61131550588f60a24George Mountimport java.util.ArrayList
5234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mountimport java.util.HashMap
5343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]").map{ it.trim() }.joinToCamelCaseAsVar()
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
56019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarenum class Scope {
57019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    FIELD
58019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    METHOD
59019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    FLAG
60019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    EXECUTE_PENDING_METHOD
61019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    CONSTRUCTOR_PARAM
62019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar}
63019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
65019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val usedFieldNames = hashMapOf<Scope, MutableSet<String>>();
66019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    {
67019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        Scope.values().forEach { usedFieldNames[it] = hashSetOf<String>() }
68019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    }
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val localizedFlags = arrayListOf<FlagSet>()
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun localizeFlag(set : FlagSet, name:String) : FlagSet {
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        localizedFlags.add(set)
73019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        val result = getUniqueName(name, Scope.FLAG)
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        set.setLocalName(result)
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return set
76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
78019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    fun getUniqueName(base : String, scope : Scope) : String {
79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var candidate = base
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        var i = 0
81019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        while (usedFieldNames[scope].contains(candidate)) {
82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            i ++
83d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            candidate = base + i
84d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
85019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        usedFieldNames[scope].add(candidate)
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return candidate
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
90de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval ExprModel.ext by Delegates.lazy { target : ExprModel ->
91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    ExprModelExt()
92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
94019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarfun ExprModel.getUniqueFieldName(base : String) : String = ext.getUniqueName(base, Scope.FIELD)
95019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarfun ExprModel.getUniqueMethodName(base : String) : String = ext.getUniqueName(base, Scope.METHOD)
96019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarfun ExprModel.getUniqueFlagName(base : String) : String = ext.getUniqueName(base, Scope.FLAG)
97019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarfun ExprModel.getConstructorParamName(base : String) : String = ext.getUniqueName(base, Scope.CONSTRUCTOR_PARAM)
98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
99d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
101019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// not necessarily unique. Uniqueness is solved per scope
102019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.readableName by Delegates.lazy { target: BindingTarget ->
10300da715547ee7d5d38a3b8576090ca427a94daa5George Mount    if (target.getId() == null) {
104019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        "boundView" + indexFromTag(target.getTag())
10500da715547ee7d5d38a3b8576090ca427a94daa5George Mount    } else {
106019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        target.getId().androidId().stripNonJava()
10700da715547ee7d5d38a3b8576090ca427a94daa5George Mount    }
108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
1097551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
110de38dd3ef0577d25b2d59863603abe5750d0c231George Mountfun BindingTarget.superConversion(variable : String) : String {
11196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    if (getResolvedType() != null && getResolvedType().extendsViewStub()) {
112de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "new android.databinding.ViewStubProxy((android.view.ViewStub) ${variable})"
113de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
114de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return "(${interfaceType}) ${variable}"
115de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
116de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
117de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
118019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.fieldName : String by Delegates.lazy { target : BindingTarget ->
119019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val name : String
120019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    if (target.getId() == null) {
121019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        name = "m${target.readableName}"
122019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    } else {
123019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        name = target.readableName
12434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
125019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    target.getModel().getUniqueFieldName(name)
126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
128de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.androidId by Delegates.lazy { target : BindingTarget ->
12943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    "R.id.${target.getId().androidId()}"
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
132de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval BindingTarget.interfaceType by Delegates.lazy { target : BindingTarget ->
133de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    if (target.getResolvedType() != null && target.getResolvedType().extendsViewStub()) {
134de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        "android.databinding.ViewStubProxy"
135de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    } else {
136de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        target.getInterfaceType()
137de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
138de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
139de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
140019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval BindingTarget.constructorParamName by Delegates.lazy { target : BindingTarget ->
141019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    target.getModel().getConstructorParamName(target.readableName)
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
144019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// not necessarily unique. Uniqueness is decided per scope
145de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.readableName by Delegates.lazy { expr : Expr ->
146019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val stripped = "${expr.getUniqueKey().stripNonJava()}"
147b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar    L.d("readableUniqueName for [%s] %s is %s", System.identityHashCode(expr), expr.getUniqueKey(), stripped)
148019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    stripped
149de38dd3ef0577d25b2d59863603abe5750d0c231George Mount}
150de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
151de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.fieldName by Delegates.lazy { expr : Expr ->
152019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueFieldName("m${expr.readableName.capitalize()}")
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
155019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval Expr.executePendingLocalName by Delegates.lazy { expr : Expr ->
156019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    if(expr.isVariable()) expr.fieldName else "${expr.getModel().ext.getUniqueName(expr.readableName, Scope.EXECUTE_PENDING_METHOD)}"
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
159de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.setterName by Delegates.lazy { expr : Expr ->
160019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("set${expr.readableName.capitalize()}")
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
163de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.onChangeName by Delegates.lazy { expr : Expr ->
164019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("onChange${expr.readableName.capitalize()}")
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
167de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.getterName by Delegates.lazy { expr : Expr ->
168019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("get${expr.readableName.capitalize()}")
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
171de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagName by Delegates.lazy { expr : Expr ->
172019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueFlagName("sFlag${expr.readableName.capitalize()}")
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
176e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarfun Expr.toCode(full : Boolean = false) : KCode = CodeGenUtil.toCode(this, full)
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
183de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagSet by Delegates.lazy { expr : Expr ->
184d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
187de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagSet by Delegates.lazy { expr : Expr ->
188d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getId())
189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
1917b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarval Expr.shouldReadFlagSet by Delegates.versionedLazy { expr : Expr ->
192d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
195de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlags by Delegates.lazy { expr : Expr ->
196d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
197d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
199d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
215d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (getLocalName() == null) binaryCode(bucketIndex)
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
217d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
218d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
219d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
220d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
221d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun longToBinary(l : Long) =
222d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        "0b${java.lang.Long.toBinaryString(l)}L"
223d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
224d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
225d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
226d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
228d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
23696e1c821dd446d1ed78f8ae61131550588f60a24George Mountfun indexFromTag(tag : String) : kotlin.Int {
23796e1c821dd446d1ed78f8ae61131550588f60a24George Mount    val startIndex : kotlin.Int
2387ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    if (tag.startsWith("binding_")) {
2397ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        startIndex = "binding_".length();
24096e1c821dd446d1ed78f8ae61131550588f60a24George Mount    } else {
24196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        startIndex = tag.lastIndexOf('_') + 1
24296e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
24396e1c821dd446d1ed78f8ae61131550588f60a24George Mount    return Integer.parseInt(tag.substring(startIndex))
24496e1c821dd446d1ed78f8ae61131550588f60a24George Mount}
24596e1c821dd446d1ed78f8ae61131550588f60a24George Mount
24643596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
247d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
24834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
24943596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
25043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
25143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
25243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
25343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
25443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
256d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
25743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
258dea555cf42dc3583604699c8c018d22681f56166George Mount    val className = layoutBinder.getImplementationName()
259d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
260dea555cf42dc3583604699c8c018d22681f56166George Mount    val baseClassName = "${layoutBinder.getClassName()}"
261d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2627551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
2637551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
2647551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
2657551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
26643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
26743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
26843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2705bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
2715bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
2725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
273d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public fun write(minSdk : kotlin.Int) : String  {
2755bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
27634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
2775bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
278a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
279a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
2805bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
281dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
282dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
283dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends ${baseClassName}"
284dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
285dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends android.databinding.ViewDataBinding"
286dea555cf42dc3583604699c8c018d22681f56166George Mount            }
287dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public class ${classDeclaration} {") {
2884c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
2895bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
2905bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
29196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab(declareConstructor(minSdk))
2925bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
293447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab(declareHasPendingBindings())
2945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
2955bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
2965bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
2975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
2985bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
2994c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3005bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
302dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
303dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
304dea555cf42dc3583604699c8c018d22681f56166George Mount                }
3055bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3075bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3085bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3095bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
31134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
31296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getBindingTargets().filter{
31396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && it.getTag() != null && !it.isBinder()
31434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
31596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        taggedViews.forEach {
31696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it, indexFromTag(it.getTag()))
31796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
31896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val indexStart = maxIndex() + 1
31996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getBindingTargets().filter{
32096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && !taggedViews.contains(it)
32196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }.withIndex().forEach {
32296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it.value, it.index + indexStart)
32334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
32434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
3254c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
32696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        nl("private static final android.databinding.ViewDataBinding.IncludedLayoutIndex[][] sIncludes;")
3274c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
3284c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
3294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
3304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
3314c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
33200da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
33396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val numBindings = layoutBinder.getBindingTargets().filter{ it.isUsed() }.count()
33496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("sIncludes = new android.databinding.ViewDataBinding.IncludedLayoutIndex[${numBindings}][];")
33596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
33696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder() }.forEach {
33796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val includeTag = it.getTag();
33896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val parent = layoutBinder.getBindingTargets().firstOrNull {
33996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        it.isUsed() && !it.isBinder() && includeTag.equals(it.getTag())
34096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (parent == null) {
34296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        throw IllegalStateException("Could not find parent of include file")
34396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    var list = includeMap.get(parent)
34596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (list == null) {
34696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        list = ArrayList<BindingTarget>()
34796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.put(parent, list)
34896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    list.add(it)
3504c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
35196e1c821dd446d1ed78f8ae61131550588f60a24George Mount
35296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                includeMap.keySet().forEach {
35396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val index = indices.get(it)
35496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("sIncludes[${index}] = new android.databinding.ViewDataBinding.IncludedLayoutIndex[] {") {
35596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.get(it).forEach {
35696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            val bindingIndex = indices.get(it)
35796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            val layoutName = it.getIncludedLayout()
35896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            tab("new android.databinding.ViewDataBinding.IncludedLayoutIndex(\"${layoutName}\", ${bindingIndex}, R.layout.${layoutName}),")
35996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        }
36096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
36196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("};")
36296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
36396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
36496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val viewsWithIds = layoutBinder.getBindingTargets().filter {
36596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                it.isUsed() && !it.isBinder() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
36600da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
36796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (viewsWithIds.isEmpty()) {
3684c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
36900da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
3704c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
37196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                viewsWithIds.forEach {
37234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sViewsWithIds.put(${it.androidId}, ${indices.get(it)});")
3734c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
37400da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
3754c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
3764c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
3774c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
37896e1c821dd446d1ed78f8ae61131550588f60a24George Mount
37996e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun maxIndex() : kotlin.Int {
38096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val maxIndex = indices.values().max()
38196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (maxIndex == null) {
38296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return -1
38396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
38496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return maxIndex
38596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
38696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
38796e1c821dd446d1ed78f8ae61131550588f60a24George Mount
38896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun declareConstructor(minSdk : kotlin.Int) = kcode("") {
38996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val bindingCount = maxIndex() + 1
39096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val parameterType : String
39196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val superParam : String
39296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (layoutBinder.isMerge()) {
39396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View[]"
39496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root[0]"
39596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
39696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View"
39796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root"
39896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
39996e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val rootTagsSupported = minSdk >= 14
400dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
401dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
40296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public ${className}(${parameterType} root) {") {
40396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("this(${superParam}, mapBindings(root, ${bindingCount}, sIncludes, sViewsWithIds));")
404dea555cf42dc3583604699c8c018d22681f56166George Mount            }
405dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
40696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("private ${className}(${parameterType} root, Object[] bindings) {") {
40796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("super(${superParam}, ${model.getObservables().size()}") {
40896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    layoutBinder.getSortedTargets().filter { it.getId() != null }.forEach {
409dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
41034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
411dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
41234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
41334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
414dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
41596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public ${baseClassName}(${parameterType} root) {") {
41696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("super(${superParam}, ${model.getObservables().size()});")
41796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("final Object[] bindings = mapBindings(root, ${bindingCount}, sIncludes, sViewsWithIds);")
418dea555cf42dc3583604699c8c018d22681f56166George Mount            }
419dea555cf42dc3583604699c8c018d22681f56166George Mount        }
42096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        tab("setRootTag(root);")
42196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getSortedTargets().filter{it.isUsed()}
422dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
423dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!layoutBinder.hasVariations() || it.getId() == null) {
424dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
425dea555cf42dc3583604699c8c018d22681f56166George Mount            }
426dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!it.isBinder()) {
427de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                if (it.getResolvedType() != null && it.getResolvedType().extendsViewStub()) {
428de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
429de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
43096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (it.supportsTag() && it.getTag() != null &&
4317ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        (rootTagsSupported || it.getTag().startsWith("binding_"))) {
432dea555cf42dc3583604699c8c018d22681f56166George Mount                    val originalTag = it.getOriginalTag();
433dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
434dea555cf42dc3583604699c8c018d22681f56166George Mount                    if (originalTag != null) {
435dea555cf42dc3583604699c8c018d22681f56166George Mount                        tagValue = "\"${originalTag}\""
436dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
437dea555cf42dc3583604699c8c018d22681f56166George Mount                            var packageName = layoutBinder.getModulePackage()
438dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
439dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
44000da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
441dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
442dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
443dea555cf42dc3583604699c8c018d22681f56166George Mount                            tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
44400da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
44500da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
446dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab("this.${it.fieldName}.setTag(${tagValue});")
4477551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
448d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
449d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
450dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
4510fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
452d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
453d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
454dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
455dea555cf42dc3583604699c8c018d22681f56166George Mount        if (!target.isUsed()) {
456dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
457dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
45896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val index = indices.get(target)
459dea555cf42dc3583604699c8c018d22681f56166George Mount            if (index == null) {
46096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                throw IllegalStateException("Unknown binding target")
461dea555cf42dc3583604699c8c018d22681f56166George Mount            }
46296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val variableName = "bindings[${index}]"
463dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
464dea555cf42dc3583604699c8c018d22681f56166George Mount        }
465dea555cf42dc3583604699c8c018d22681f56166George Mount    }
466dea555cf42dc3583604699c8c018d22681f56166George Mount
467d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
4687551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
4697551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
470019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            val fs = FlagSet(layoutBinder.getModel().getInvalidateAnyBitSet(),
471019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    layoutBinder.getModel().getFlagBucketCount());
4721c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
4731c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
4741c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
4751c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
4761c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
4775bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
4787551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
4797551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
480d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4810fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
482d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
483d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
484447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    fun declareHasPendingBindings()  = kcode("") {
485447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("@Override")
486447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("public boolean hasPendingBindings() {") {
487447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            if (mDirtyFlags.buckets.size() > 0) {
488447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("synchronized(this) {") {
489447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    val flagCheck = 0.rangeTo(mDirtyFlags.buckets.size() - 1).map {
490447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                            "${mDirtyFlags.localValue(it)} != 0"
491447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }.joinToString(" || ")
492447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("if (${flagCheck}) {") {
493447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                        tab("return true;")
494447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }
495447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("}")
496447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
497447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
498447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
499447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            includedBinders.filter{it.isUsed()}.forEach { binder ->
500447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("if (${binder.fieldName}.hasPendingBindings()) {") {
501447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("return true;")
502447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
503447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
504447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
505447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            tab("return false;")
506447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        }
507447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("}")
508447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    }
509447971abca811b11b8c1d8e7bfaa294856d03c16George Mount
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 {
535019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
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) {
547019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
54818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
549019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                        tab("updateRegistration(${it.getId()}, ${it.readableName});");
55018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
551019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.readableName};")
55218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
55318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
5541c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("synchronized(this) {") {
5551c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
5561c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
5571c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        }
5581c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    } tab ("}")
55918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
560d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
56118243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
56218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
56318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
56418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
565d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
56618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
567d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
568d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
569d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
570d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
571d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
57234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
57334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
5744c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
575d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
576d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
577d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
578d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
579d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
580d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
582d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
58434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
58534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
586d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
588019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableName}, int fieldId) {") {
589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
590d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
591d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    accessedFields.filter { it.canBeInvalidated() }
592d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
593d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
59443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
5961c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    tab("synchronized(this) {") {
5971c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
5981c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                            tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
5991c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        }
6001c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    } tab("}")
601d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
602d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
603d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
604d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
60543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
606d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
6071c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        tab("synchronized(this) {") {
6081c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            mDirtyFlags.mapOr(flagSet) { suffix, index ->
6091c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
6101c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            }
6111c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        } tab("}")
612d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
613d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
614d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
615d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
616d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
617d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
618d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
61934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
62034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
621d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
622d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
623d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
624d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
625dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
62696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getSortedTargets().filter {it.isUsed() && (oneLayout || it.getId() == null)}.forEach {
627dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
628dea555cf42dc3583604699c8c018d22681f56166George Mount            if (oneLayout && it.getId() != null) {
629dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
630dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
631dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
632dea555cf42dc3583604699c8c018d22681f56166George Mount            }
633dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${access} final ${it.interfaceType} ${it.fieldName};")
634d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
635d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
636d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
637d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
6385bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
6390fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
640d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
641d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
642d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
643d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
644d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
645de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
6460fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
647d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
648d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = ${longToBinary(value)};")
649d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
650d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
651d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
652d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
653d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
654d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
655d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
656d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
657d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
658d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
659d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
660d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
661d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
662d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
6634c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
6640fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
665e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        nl("protected void executeBindings() {") {
666d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
667d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
668d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
6691c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = 0;")
670d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
6711c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
6721c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..mDirtyFlags.buckets.size() - 1)) {
6731c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
6741c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = 0;")
6751c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
6761c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
677e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar            model.getPendingExpressions().filterNot {!it.canBeEvaluatedToAVariable() || it.isVariable()}.forEach {
678019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                tab("${it.getResolvedType().toJavaCode()} ${it.executePendingLocalName} = ${it.getDefaultValue()};")
679d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
680b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar            L.d("writing executePendingBindings for %s", className)
681d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
68274f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
683b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                L.d("batch: %s", batch)
684d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val mJustRead = arrayListOf<Expr>()
685d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
6860fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    val readNow = batch.filter { it.shouldReadNow(mJustRead) }
687d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
688d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
689d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
690b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                    L.d("new read now. batch size: %d, readNow size: %d", batch.size(), readNow.size())
691d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
692d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    readNow.forEach {
6930fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        nl(readWithDependants(it, mJustRead, batch, tmpDirtyFlags))
694d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
695d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    batch.removeAll(mJustRead)
696d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
6970fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
698d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } while(model.markBitsRead())
6997b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            // verify everything is read.
7007b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
7017b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            if (batch.isNotEmpty()) {
7027b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                L.e("could not generate code for %s. This might be caused by circular dependencies."
7037b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                        + "Please report on b.android.com", layoutBinder.getLayoutname())
7047b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            }
705d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
70696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
707d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
708d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .groupBy { it.getExpr() }
709d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .forEach {
710d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.key.dirtyFlagSet
711d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
712d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
713d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }.joinToString(" || ")
714d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }) {") {
715d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
71697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                tab("// api target ${binding.getMinApi()}")
71734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val fieldName : String
71834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                if (binding.getTarget().getViewClass().
71934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                        equals(binding.getTarget().getInterfaceType())) {
72034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "this.${binding.getTarget().fieldName}"
72134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
72234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "((${binding.getTarget().getViewClass()}) this.${binding.getTarget().fieldName})"
72334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
724e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar                                val bindingCode = binding.toJavaCode(fieldName)
72597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                if (binding.getMinApi() > 1) {
7264c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                                    tab("if(getBuildSdkInt() >= ${binding.getMinApi()}) {") {
72797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                        tab("$bindingCode;")
72897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    }
72997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("}")
73097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                } else {
73197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("$bindingCode;")
73297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                }
733d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
734d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
735d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("}")
736d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
7375bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
7384c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
7397551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
74096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{
741de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                it.isUsed() && it.getResolvedType() != null && it.getResolvedType().extendsViewStub()
742de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }.forEach {
743de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("if (${it.fieldName}.getBinding() != null) {") {
744de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("${it.fieldName}.getBinding().executePendingBindings();")
745de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
746de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("}")
747de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
748d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
7490fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
750d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
751d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
752d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    fun readWithDependants(expr : Expr, mJustRead : MutableList<Expr>, batch : MutableList<Expr>,
753d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tmpDirtyFlags : FlagSet, inheritedFlags : FlagSet? = null) : KCode = kcode("") {
754d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mJustRead.add(expr)
755b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar        L.d("%s / readWithDependants %s", className, expr.getUniqueKey());
756d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val flagSet = expr.shouldReadFlagSet
757d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
758b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar        L.d("flag set:%s . inherited flags: %s. need another if: %s", flagSet, inheritedFlags, needsIfWrapper);
759d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
76043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
76143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.joinToString(" || ")
762d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        })"
763d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
764d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val readCode = kcode("") {
765e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar            if (expr.canBeEvaluatedToAVariable() && !expr.isVariable()) {
766d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // it is not a variable read it.
767d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("// read ${expr.getUniqueKey()}")
768d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // create an if case for all dependencies that might be null
769d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val nullables = expr.getDependencies().filter {
770e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount                    it.isMandatory() && it.getOther().getResolvedType().isNullable()
77174f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                }.map { it.getOther() }
772d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
773019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab ("if ( ${nullables.map { "${it.executePendingLocalName} != null" }.joinToString(" && ")}) {") {
774019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                        tab("${expr.executePendingLocalName}").app(" = ", expr.toCode(true)).app(";")
775d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
776d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("}")
777d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                } else {
778019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("${expr.executePendingLocalName}").app(" = ", expr.toCode(true)).app(";")
779d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7807920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                if (expr.isObservable()) {
781019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("updateRegistration(${expr.getId()}, ${expr.executePendingLocalName});")
782d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7830fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            }
784d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7850fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            // if I am the condition for an expression, set its flag
7860fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            val conditionals = expr.getDependants().filter { !it.isConditional()
7870fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    && it.getDependant() is TernaryExpr && (it.getDependant() as TernaryExpr).getPred() == expr }
7880fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    .map { it.getDependant() }
7890fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            if (conditionals.isNotEmpty()) {
7900fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// setting conditional flags")
791019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                tab("if (${expr.executePendingLocalName}) {") {
7920fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
7930fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(true)
7940fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
7950fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
796d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
797d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
798d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7990fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("} else {") {
8000fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8010fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(false)
8020fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8030fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
8040fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
8050fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
8060fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                } tab("}")
807d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
8080fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
809d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val chosen = expr.getDependants().filter {
810d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val dependant = it.getDependant()
811d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                batch.contains(dependant) &&
812d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadFlagSet.andNot(flagSet).isEmpty() &&
813d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadNow(mJustRead)
814d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
815d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (chosen.isNotEmpty()) {
816d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
817d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                chosen.forEach {
818d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                    nl(readWithDependants(it.getDependant(), mJustRead, batch, tmpDirtyFlags, nextInheritedFlags))
819d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
820d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
821d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
822d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (needsIfWrapper) {
823d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab(ifClause) {
824d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" {")
825d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                nl(readCode)
826d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
827d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab("}")
828d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
829d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            nl(readCode)
830d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
831d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
83243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
833dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
83496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (!layoutBinder.isMerge()) {
8359bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
836f80b08430f11515ff944f89006799f21545602b9George Mount                tab("return bind(inflater.inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot));")
837dea555cf42dc3583604699c8c018d22681f56166George Mount            }
83896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
8399bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
8409bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount                tab("return bind(inflater.inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false));")
84196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
84296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
84396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} bind(android.view.View view) {") {
84496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("if (!\"${layoutBinder.getTag()}_0\".equals(view.getTag())) {") {
845f80b08430f11515ff944f89006799f21545602b9George Mount                    tab("throw new RuntimeException(\"view tag isn't correct on view:\" + view.getTag());")
84696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
84796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("}")
84896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("return new ${baseClassName}(view);")
84996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
85096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
851dea555cf42dc3583604699c8c018d22681f56166George Mount        }
852dea555cf42dc3583604699c8c018d22681f56166George Mount    }
853dea555cf42dc3583604699c8c018d22681f56166George Mount
8544c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public fun writeBaseClass() : String =
85543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
856fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
857fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
858fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
8594c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
86096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
861de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("public final ${it.interfaceType} ${it.fieldName};")
86234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
86334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
86434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab("protected ${baseClassName}(android.view.View root_, int localFieldCount") {
86596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
866019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab(", ${it.interfaceType} ${it.constructorParamName}")
86734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
86834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
86934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
87034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                tab("super(root_, localFieldCount);")
87196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
872019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.constructorParamName};")
87334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
8744c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
8754c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
8764c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
87743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
87818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
879895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    //it.getExpandedUserDefinedType(ModelAnalyzer.getInstance());
880895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
881019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("public abstract void ${it.setterName}(${type} ${it.readableName});")
88218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
88343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
8849bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
8859bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount                tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true);")
88643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
8874c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
8889bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
8899bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount                tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false);")
8904c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
8914c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
8924c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
893ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount                tab("return (${baseClassName})bind(view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
8944c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
8954c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
89643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
89743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
898dea555cf42dc3583604699c8c018d22681f56166George Mount}
899