LayoutBinderWriter.kt revision 20c7182163d99575d382e065f5a5fe45ed6b87e2
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
54fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyarfun String.stripNonJava() = this.split("[^a-zA-Z0-9]".toRegex()).map{ it.trim() }.joinToCamelCaseAsVar()
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
56019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarenum class Scope {
57fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    FIELD,
58fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    METHOD,
59fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    FLAG,
60fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    EXECUTE_PENDING_METHOD,
61019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    CONSTRUCTOR_PARAM
62019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar}
63019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar
64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarclass ExprModelExt {
65019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    val usedFieldNames = hashMapOf<Scope, MutableSet<String>>();
66fda1703c88eb22e9f166d957d6bda2cd8d645b8fYigit Boyar    init {
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
15520c7182163d99575d382e065f5a5fe45ed6b87e2George Mountval Expr.oldValueName by Delegates.lazy { expr : Expr ->
15620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    expr.getModel().getUniqueFieldName("mOld${expr.readableName.capitalize()}")
15720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount}
15820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
159019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarval Expr.executePendingLocalName by Delegates.lazy { expr : Expr ->
1604a81aabc49f6c881d960cd541adda7de9625277aYigit Boyar    "${expr.getModel().ext.getUniqueName(expr.readableName, Scope.EXECUTE_PENDING_METHOD)}"
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
163de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.setterName by Delegates.lazy { expr : Expr ->
164019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("set${expr.readableName.capitalize()}")
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
167de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.onChangeName by Delegates.lazy { expr : Expr ->
168019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("onChange${expr.readableName.capitalize()}")
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
171de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.getterName by Delegates.lazy { expr : Expr ->
172019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueMethodName("get${expr.readableName.capitalize()}")
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
175de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagName by Delegates.lazy { expr : Expr ->
176019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar    expr.getModel().getUniqueFlagName("sFlag${expr.readableName.capitalize()}")
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
180e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyarfun Expr.toCode(full : Boolean = false) : KCode = CodeGenUtil.toCode(this, full)
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic()
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix"
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
187de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.dirtyFlagSet by Delegates.lazy { expr : Expr ->
188d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount())
189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
191de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.invalidateFlagSet by Delegates.lazy { expr : Expr ->
192d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getId())
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
1957b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarval Expr.shouldReadFlagSet by Delegates.versionedLazy { expr : Expr ->
196d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount())
197d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
199de38dd3ef0577d25b2d59863603abe5750d0c231George Mountval Expr.conditionalFlags by Delegates.lazy { expr : Expr ->
200d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    arrayListOf(FlagSet(expr.getRequirementFlagIndex(false)),
201d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            FlagSet(expr.getRequirementFlagIndex(true)))
202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0]
205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) {
207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    buckets.withIndex().forEach {
208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (it.value != 0L) {
209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            cb(getWordSuffix(it.index), buckets[it.index])
210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
213d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
214d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.getWordSuffix(wordIndex : Int) : String {
215d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return if(wordIndex == 0) "" else "_${wordIndex}"
216d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
217d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
218d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun FlagSet.localValue(bucketIndex : Int) =
219d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (getLocalName() == null) binaryCode(bucketIndex)
220d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        else "${getLocalName()}${getWordSuffix(bucketIndex)}"
221d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
222d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun FlagSet.binaryCode(bucketIndex : Int) = longToBinary(buckets[bucketIndex])
223d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
224d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
225d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyarfun longToBinary(l : Long) =
226d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        "0b${java.lang.Long.toBinaryString(l)}L"
227d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
228d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> {
229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val min = Math.min(buckets.size(), other.buckets.size())
230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val result = arrayListOf<T>()
231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    for (i in 0..(min - 1)) {
232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        // if these two can match by any chance, call the callback
233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (intersect(other, i)) {
234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            result.add(cb(getWordSuffix(i), i))
235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    return result
238d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
239d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
24096e1c821dd446d1ed78f8ae61131550588f60a24George Mountfun indexFromTag(tag : String) : kotlin.Int {
24196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    val startIndex : kotlin.Int
2427ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount    if (tag.startsWith("binding_")) {
2437ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        startIndex = "binding_".length();
24496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    } else {
24596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        startIndex = tag.lastIndexOf('_') + 1
24696e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
24796e1c821dd446d1ed78f8ae61131550588f60a24George Mount    return Integer.parseInt(tag.substring(startIndex))
24896e1c821dd446d1ed78f8ae61131550588f60a24George Mount}
24996e1c821dd446d1ed78f8ae61131550588f60a24George Mount
25043596c2b2997e40b709627419732100d78a62ff0Yigit Boyarclass LayoutBinderWriter(val layoutBinder : LayoutBinder) {
251d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    val model = layoutBinder.getModel()
25234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    val indices = HashMap<BindingTarget, kotlin.Int>()
25343596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val mDirtyFlags by Delegates.lazy {
25443596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        val fs = FlagSet(BitSet(), model.getFlagBucketCount());
25543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        Arrays.fill(fs.buckets, -1)
25643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs.setDynamic(true)
25743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.localizeFlag(fs, "mDirtyFlags")
25843596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        fs
259d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
260d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
26143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } }
262dea555cf42dc3583604699c8c018d22681f56166George Mount    val className = layoutBinder.getImplementationName()
263d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
264dea555cf42dc3583604699c8c018d22681f56166George Mount    val baseClassName = "${layoutBinder.getClassName()}"
265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2667551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    val includedBinders by Delegates.lazy {
2677551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        layoutBinder.getBindingTargets().filter { it.isBinder() }
2687551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar    }
2697551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar
27043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    val variables by Delegates.lazy {
27143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() }
27243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar    }
273d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
2745bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    val usedVariables by Delegates.lazy {
2755bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filter {it.isUsed()}
2765bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27896e1c821dd446d1ed78f8ae61131550588f60a24George Mount    public fun write(minSdk : kotlin.Int) : String  {
2795bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        layoutBinder.resolveWhichExpressionsAreUsed()
28034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        calculateIndices();
2815bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        return kcode("package ${layoutBinder.getPackage()};") {
282a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.R;")
283a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            nl("import ${layoutBinder.getModulePackage()}.BR;")
2845bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("import android.view.View;")
285dea555cf42dc3583604699c8c018d22681f56166George Mount            val classDeclaration : String
286dea555cf42dc3583604699c8c018d22681f56166George Mount            if (layoutBinder.hasVariations()) {
287dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends ${baseClassName}"
288dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
289dea555cf42dc3583604699c8c018d22681f56166George Mount                classDeclaration = "${className} extends android.databinding.ViewDataBinding"
290dea555cf42dc3583604699c8c018d22681f56166George Mount            }
291dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("public class ${classDeclaration} {") {
2924c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(declareIncludeViews())
2935bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareViews())
2945bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareVariables())
29520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                tab(declareBoundValues())
29696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab(declareConstructor(minSdk))
2975bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareInvalidateAll())
298447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab(declareHasPendingBindings())
2995bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareLog())
3005bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareSetVariable())
3015bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(variableSettersAndGetters())
3025bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(onFieldChange())
3035bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3044c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab(executePendingBindings())
3055bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar
3065bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab(declareDirtyFlags())
307dea555cf42dc3583604699c8c018d22681f56166George Mount                if (!layoutBinder.hasVariations()) {
308dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(declareFactories())
309dea555cf42dc3583604699c8c018d22681f56166George Mount                }
3105bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
3115bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
3125bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab(flagMapping())
3135bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            tab("//end")
3145bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }.generate()
3155bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar    }
31634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    fun calculateIndices() : Unit {
31796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getBindingTargets().filter{
318d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount            it.isUsed() && it.getTag() != null && !it.isBinder()
31934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
32096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        taggedViews.forEach {
32196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it, indexFromTag(it.getTag()))
32296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
32396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val indexStart = maxIndex() + 1
32496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getBindingTargets().filter{
32596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            it.isUsed() && !taggedViews.contains(it)
32696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }.withIndex().forEach {
32796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            indices.put(it.value, it.index + indexStart)
32834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        }
32934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount    }
3304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun declareIncludeViews() = kcode("") {
33196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        nl("private static final android.databinding.ViewDataBinding.IncludedLayoutIndex[][] sIncludes;")
3324c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("private static final android.util.SparseIntArray sViewsWithIds;")
3334c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("static {") {
3344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            val hasBinders = layoutBinder.getBindingTargets().firstOrNull{ it.isUsed() && it.isBinder()} != null
3354c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            if (!hasBinders) {
3364c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sIncludes = null;")
33700da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
33896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val numBindings = layoutBinder.getBindingTargets().filter{ it.isUsed() }.count()
33996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("sIncludes = new android.databinding.ViewDataBinding.IncludedLayoutIndex[${numBindings}][];")
34096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                val includeMap = HashMap<BindingTarget, ArrayList<BindingTarget>>()
34196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getBindingTargets().filter{ it.isUsed() && it.isBinder() }.forEach {
34296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val includeTag = it.getTag();
34396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val parent = layoutBinder.getBindingTargets().firstOrNull {
34496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        it.isUsed() && !it.isBinder() && includeTag.equals(it.getTag())
34596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (parent == null) {
34796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        throw IllegalStateException("Could not find parent of include file")
34896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
34996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    var list = includeMap.get(parent)
35096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    if (list == null) {
35196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        list = ArrayList<BindingTarget>()
35296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.put(parent, list)
35396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
35496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    list.add(it)
3554c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
35696e1c821dd446d1ed78f8ae61131550588f60a24George Mount
35796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                includeMap.keySet().forEach {
35896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    val index = indices.get(it)
35996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("sIncludes[${index}] = new android.databinding.ViewDataBinding.IncludedLayoutIndex[] {") {
36096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        includeMap.get(it).forEach {
36196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            val bindingIndex = indices.get(it)
36296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            val layoutName = it.getIncludedLayout()
36396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                            tab("new android.databinding.ViewDataBinding.IncludedLayoutIndex(\"${layoutName}\", ${bindingIndex}, R.layout.${layoutName}),")
36496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        }
36596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    }
36696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    tab("};")
36796e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
36896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
36996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val viewsWithIds = layoutBinder.getBindingTargets().filter {
370d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount                it.isUsed() && !it.isBinder() && (!it.supportsTag() || (it.getId() != null && it.getTag() == null))
37100da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
37296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            if (viewsWithIds.isEmpty()) {
3734c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = null;")
37400da715547ee7d5d38a3b8576090ca427a94daa5George Mount            } else {
3754c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("sViewsWithIds = new android.util.SparseIntArray();")
37696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                viewsWithIds.forEach {
37734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    tab("sViewsWithIds.put(${it.androidId}, ${indices.get(it)});")
3784c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                }
37900da715547ee7d5d38a3b8576090ca427a94daa5George Mount            }
3804c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        }
3814c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount        nl("}")
3824c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    }
38396e1c821dd446d1ed78f8ae61131550588f60a24George Mount
38496e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun maxIndex() : kotlin.Int {
38596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val maxIndex = indices.values().max()
38696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (maxIndex == null) {
38796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return -1
38896e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
38996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return maxIndex
39096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
39196e1c821dd446d1ed78f8ae61131550588f60a24George Mount    }
39296e1c821dd446d1ed78f8ae61131550588f60a24George Mount
39396e1c821dd446d1ed78f8ae61131550588f60a24George Mount    fun declareConstructor(minSdk : kotlin.Int) = kcode("") {
39496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val bindingCount = maxIndex() + 1
39596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val parameterType : String
39696e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val superParam : String
39796e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (layoutBinder.isMerge()) {
39896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View[]"
39996e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root[0]"
40096e1c821dd446d1ed78f8ae61131550588f60a24George Mount        } else {
40196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            parameterType = "View"
40296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            superParam = "root"
40396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
40496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val rootTagsSupported = minSdk >= 14
405dea555cf42dc3583604699c8c018d22681f56166George Mount        if (layoutBinder.hasVariations()) {
406dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("")
40796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public ${className}(${parameterType} root) {") {
40896e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("this(${superParam}, mapBindings(root, ${bindingCount}, sIncludes, sViewsWithIds));")
409dea555cf42dc3583604699c8c018d22681f56166George Mount            }
410dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("}")
41196e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("private ${className}(${parameterType} root, Object[] bindings) {") {
41296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("super(${superParam}, ${model.getObservables().size()}") {
41396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                    layoutBinder.getSortedTargets().filter { it.getId() != null }.forEach {
414dea555cf42dc3583604699c8c018d22681f56166George Mount                        tab(", ${fieldConversion(it)}")
41534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                    }
416dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab(");")
41734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
41834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
419dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
42096e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public ${baseClassName}(${parameterType} root) {") {
42196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("super(${superParam}, ${model.getObservables().size()});")
42296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("final Object[] bindings = mapBindings(root, ${bindingCount}, sIncludes, sViewsWithIds);")
423dea555cf42dc3583604699c8c018d22681f56166George Mount            }
424dea555cf42dc3583604699c8c018d22681f56166George Mount        }
42596e1c821dd446d1ed78f8ae61131550588f60a24George Mount        val taggedViews = layoutBinder.getSortedTargets().filter{it.isUsed()}
426dea555cf42dc3583604699c8c018d22681f56166George Mount        taggedViews.forEach {
427dea555cf42dc3583604699c8c018d22681f56166George Mount            if (!layoutBinder.hasVariations() || it.getId() == null) {
428dea555cf42dc3583604699c8c018d22681f56166George Mount                tab("this.${it.fieldName} = ${fieldConversion(it)};")
429dea555cf42dc3583604699c8c018d22681f56166George Mount            }
430d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount            if (!it.isBinder()) {
431de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                if (it.getResolvedType() != null && it.getResolvedType().extendsViewStub()) {
432de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("this.${it.fieldName}.setContainingBinding(this);")
433de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
43496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                if (it.supportsTag() && it.getTag() != null &&
4357ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        (rootTagsSupported || it.getTag().startsWith("binding_"))) {
436dea555cf42dc3583604699c8c018d22681f56166George Mount                    val originalTag = it.getOriginalTag();
437dea555cf42dc3583604699c8c018d22681f56166George Mount                    var tagValue = "null"
438dea555cf42dc3583604699c8c018d22681f56166George Mount                    if (originalTag != null) {
439dea555cf42dc3583604699c8c018d22681f56166George Mount                        tagValue = "\"${originalTag}\""
440dea555cf42dc3583604699c8c018d22681f56166George Mount                        if (originalTag.startsWith("@")) {
441dea555cf42dc3583604699c8c018d22681f56166George Mount                            var packageName = layoutBinder.getModulePackage()
442dea555cf42dc3583604699c8c018d22681f56166George Mount                            if (originalTag.startsWith("@android:")) {
443dea555cf42dc3583604699c8c018d22681f56166George Mount                                packageName = "android"
44400da715547ee7d5d38a3b8576090ca427a94daa5George Mount                            }
445dea555cf42dc3583604699c8c018d22681f56166George Mount                            val slashIndex = originalTag.indexOf('/')
446dea555cf42dc3583604699c8c018d22681f56166George Mount                            val resourceId = originalTag.substring(slashIndex + 1)
447dea555cf42dc3583604699c8c018d22681f56166George Mount                            tagValue = "root.getResources().getString(${packageName}.R.string.${resourceId})"
44800da715547ee7d5d38a3b8576090ca427a94daa5George Mount                        }
44900da715547ee7d5d38a3b8576090ca427a94daa5George Mount                    }
450dea555cf42dc3583604699c8c018d22681f56166George Mount                    tab("this.${it.fieldName}.setTag(${tagValue});")
4517551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                }
452d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
453d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4544d4979490e1fa374c0d7f3599fed0a9e83a579d0George Mount        tab("setRootTag(root);")
455dea555cf42dc3583604699c8c018d22681f56166George Mount        tab("invalidateAll();");
4560fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
457d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
458d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
459dea555cf42dc3583604699c8c018d22681f56166George Mount    fun fieldConversion(target : BindingTarget) : String {
460dea555cf42dc3583604699c8c018d22681f56166George Mount        if (!target.isUsed()) {
461dea555cf42dc3583604699c8c018d22681f56166George Mount            return "null"
462dea555cf42dc3583604699c8c018d22681f56166George Mount        } else {
46396e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val index = indices.get(target)
464dea555cf42dc3583604699c8c018d22681f56166George Mount            if (index == null) {
46596e1c821dd446d1ed78f8ae61131550588f60a24George Mount                throw IllegalStateException("Unknown binding target")
466dea555cf42dc3583604699c8c018d22681f56166George Mount            }
46796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            val variableName = "bindings[${index}]"
468dea555cf42dc3583604699c8c018d22681f56166George Mount            return target.superConversion(variableName)
469dea555cf42dc3583604699c8c018d22681f56166George Mount        }
470dea555cf42dc3583604699c8c018d22681f56166George Mount    }
471dea555cf42dc3583604699c8c018d22681f56166George Mount
472d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareInvalidateAll() = kcode("") {
4737551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("@Override")
4747551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar        nl("public void invalidateAll() {") {
475019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            val fs = FlagSet(layoutBinder.getModel().getInvalidateAnyBitSet(),
476019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    layoutBinder.getModel().getFlagBucketCount());
4771c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
4781c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..(mDirtyFlags.buckets.size() - 1))) {
4791c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
4801c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
4811c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
4825bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
4837551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar                tab("${binder.fieldName}.invalidateAll();")
4847551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
4852f64c44e4fa296cf658ca986c095eab62f82a31dYigit Boyar            tab("requestRebind();");
486d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
4870fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
488d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
489d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
490447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    fun declareHasPendingBindings()  = kcode("") {
491447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("@Override")
492447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("public boolean hasPendingBindings() {") {
493447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            if (mDirtyFlags.buckets.size() > 0) {
494447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("synchronized(this) {") {
495447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    val flagCheck = 0.rangeTo(mDirtyFlags.buckets.size() - 1).map {
496447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                            "${mDirtyFlags.localValue(it)} != 0"
497447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }.joinToString(" || ")
498447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("if (${flagCheck}) {") {
499447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                        tab("return true;")
500447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    }
501447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("}")
502447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
503447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
504447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
505447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            includedBinders.filter{it.isUsed()}.forEach { binder ->
506447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("if (${binder.fieldName}.hasPendingBindings()) {") {
507447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                    tab("return true;")
508447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                }
509447971abca811b11b8c1d8e7bfaa294856d03c16George Mount                tab("}")
510447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            }
511447971abca811b11b8c1d8e7bfaa294856d03c16George Mount            tab("return false;")
512447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        }
513447971abca811b11b8c1d8e7bfaa294856d03c16George Mount        nl("}")
514447971abca811b11b8c1d8e7bfaa294856d03c16George Mount    }
515447971abca811b11b8c1d8e7bfaa294856d03c16George Mount
516d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareSetVariable() = kcode("") {
5170fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("public boolean setVariable(int variableId, Object variable) {") {
518d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("switch(variableId) {") {
5195bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                usedVariables.forEach {
52043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab ("case ${it.getName().br()} :") {
521d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);")
522d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
523d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
524d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
525d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
526d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
527d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
528d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
5290fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
530d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
531d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
532d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareLog() = kcode("") {
5330fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("private void log(String msg, long i) {") {
534d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""")
5350fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        }
5360fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
537d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
538d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
539d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun variableSettersAndGetters() = kcode("") {
5405bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        variables.filterNot{it.isUsed()}.forEach {
541019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
5425bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("// not used, ignore")
5435bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5445bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5455bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("")
5465bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
5475bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar                tab("return ${it.getDefaultValue()};")
5485bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            }
5495bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            nl("}")
5505bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        }
5515bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
55218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount            if (it.getUserDefinedType() != null) {
553019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableName}) {") {
55418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    if (it.isObservable()) {
555019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                        tab("updateRegistration(${it.getId()}, ${it.readableName});");
55618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    }
557019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.readableName};")
55818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    // set dirty flags!
55918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    val flagSet = it.invalidateFlagSet
5601c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("synchronized(this) {") {
5611c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        mDirtyFlags.mapOr(flagSet) { suffix, index ->
5621c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
5631c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        }
5641c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    } tab ("}")
56518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("super.requestRebind();")
566d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
56718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
56818243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("")
56918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") {
57018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                    tab("return ${it.fieldName};")
571d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
57218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                nl("}")
573d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
574d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
575d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
576d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
577d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun onFieldChange() = kcode("") {
57834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("@Override")
57934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {") {
5804c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("switch (localFieldId) {") {
581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                model.getObservables().forEach {
582d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("case ${it.getId()} :") {
583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);")
584d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
586d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("}")
588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tab("return false;")
589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
59034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("}")
59134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount        nl("")
592d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
593d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.getObservables().forEach {
594019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar            nl("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableName}, int fieldId) {") {
595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("switch (fieldId) {", {
596d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>())
597c4a07bddb4dd5c3bfbecf4d87909c5b447ae56dcGeorge Mount                    accessedFields.filter { it.hasBindableAnnotations() }
598d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .groupBy { it.getName() }
599d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            .forEach {
60043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                                tab("case ${it.key.br()}:") {
601d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    val field = it.value.first()
6021c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    tab("synchronized(this) {") {
6031c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index ->
6041c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                            tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};")
6051c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                        }
6061c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                    } tab("}")
607d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                    tab("return true;")
608d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                                }
609d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
610d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
61143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar                    tab("case ${"".br()}:") {
612d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.invalidateFlagSet
6131c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        tab("synchronized(this) {") {
6141c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            mDirtyFlags.mapOr(flagSet) { suffix, index ->
6151c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                                tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};")
6161c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                            }
6171c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                        } tab("}")
618d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("return true;")
619d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
620d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
621d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                })
622d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("}")
623d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("return false;")
624d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
62534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("}")
62634a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
627d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
628d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
629d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
630d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareViews() = kcode("// views") {
631dea555cf42dc3583604699c8c018d22681f56166George Mount        val oneLayout = !layoutBinder.hasVariations();
63296e1c821dd446d1ed78f8ae61131550588f60a24George Mount        layoutBinder.getSortedTargets().filter {it.isUsed() && (oneLayout || it.getId() == null)}.forEach {
633dea555cf42dc3583604699c8c018d22681f56166George Mount            val access : String
634dea555cf42dc3583604699c8c018d22681f56166George Mount            if (oneLayout && it.getId() != null) {
635dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "public"
636dea555cf42dc3583604699c8c018d22681f56166George Mount            } else {
637dea555cf42dc3583604699c8c018d22681f56166George Mount                access = "private"
638dea555cf42dc3583604699c8c018d22681f56166George Mount            }
639dea555cf42dc3583604699c8c018d22681f56166George Mount            nl("${access} final ${it.interfaceType} ${it.fieldName};")
640d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
641d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
642d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
643d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareVariables() = kcode("// variables") {
6445bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar        usedVariables.forEach {
6450fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};")
646d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
647d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
648d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
64920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    fun declareBoundValues() = kcode("// values") {
65020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount        layoutBinder.getSortedTargets().filter { it.isUsed() }
65120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .flatMap { it.getBindings() }
65220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .filter { it.requiresOldValue() }
65320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .flatMap{ it.getComponentExpressions().toArrayList() }
65420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .groupBy { it }
65520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                .forEach {
65620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    val expr = it.getKey()
65720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    nl("private ${expr.getResolvedType().toJavaCode()} ${expr.oldValueName};")
65820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                }
65920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount    }
66020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
661d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun declareDirtyFlags() = kcode("// dirty flag") {
662d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.ext.localizedFlags.forEach { flag ->
663de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            flag.notEmpty { suffix, value ->
6640fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                nl("private")
665d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                app(" ", if(flag.isDynamic()) null else "static final");
666d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = ${longToBinary(value)};")
667d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
668d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
669d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
670d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
671d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    fun flagMapping() = kcode("/* flag mapping") {
672d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        if (model.getFlagMapping() != null) {
673d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val mapping = model.getFlagMapping()
674d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in mapping.indices) {
675d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("flag $i: ${mapping[i]}")
676d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
677d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
678d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        nl("flag mapping end*/")
679d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
680d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
6814c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    fun executePendingBindings() = kcode("") {
6820fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("@Override")
683e725f0d81e1b07e88f819be9a82181eeeb680dbfGeorge Mount        nl("protected void executeBindings() {") {
684d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
685d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            tmpDirtyFlags.setLocalName("dirtyFlags");
686d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            for (i in (0..mDirtyFlags.buckets.size() - 1)) {
6871c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = 0;")
688d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
6891c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            tab("synchronized(this) {") {
6901c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                for (i in (0..mDirtyFlags.buckets.size() - 1)) {
6911c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
6921c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                    tab("${mDirtyFlags.localValue(i)} = 0;")
6931c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar                }
6941c44adacab2c1baa937a604da136024f1e92a088Yigit Boyar            } tab("}")
6954a81aabc49f6c881d960cd541adda7de9625277aYigit Boyar            model.getPendingExpressions().filterNot {!it.canBeEvaluatedToAVariable() || (it.isVariable() && !it.isUsed())}.forEach {
6964a81aabc49f6c881d960cd541adda7de9625277aYigit Boyar                tab("${it.getResolvedType().toJavaCode()} ${it.executePendingLocalName} = ${if(it.isVariable()) it.fieldName else it.getDefaultValue()};")
697d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
698b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar            L.d("writing executePendingBindings for %s", className)
699d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            do {
70074f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
701b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                L.d("batch: %s", batch)
702d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val mJustRead = arrayListOf<Expr>()
703d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                while (!batch.none()) {
7040fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    val readNow = batch.filter { it.shouldReadNow(mJustRead) }
705d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    if (readNow.isEmpty()) {
706d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}")
707d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
708b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar                    L.d("new read now. batch size: %d, readNow size: %d", batch.size(), readNow.size())
709d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
710d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    readNow.forEach {
7110fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        nl(readWithDependants(it, mJustRead, batch, tmpDirtyFlags))
712d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
713d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    batch.removeAll(mJustRead)
714d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
7150fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// batch finished")
716d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            } while(model.markBitsRead())
7177b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            // verify everything is read.
7187b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            val batch = ExprModel.filterShouldRead(model.getPendingExpressions()).toArrayList()
7197b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            if (batch.isNotEmpty()) {
7207b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                L.e("could not generate code for %s. This might be caused by circular dependencies."
7217b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar                        + "Please report on b.android.com", layoutBinder.getLayoutname())
7227b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar            }
723d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            //
72496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
725d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .flatMap { it.getBindings() }
726d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .groupBy { it.getExpr() }
727d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .forEach {
728d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        val flagSet = it.key.dirtyFlagSet
729d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
730d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
731d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }.joinToString(" || ")
732d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }) {") {
733d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            it.value.forEach { binding ->
73497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                tab("// api target ${binding.getMinApi()}")
73534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                val fieldName : String
736d6527ee28cc3aa05818799af8def9593346f91bcGeorge Mount                                if (binding.getTarget().getViewClass().
73734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                        equals(binding.getTarget().getInterfaceType())) {
73834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "this.${binding.getTarget().fieldName}"
73934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                } else {
74034a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                    fieldName = "((${binding.getTarget().getViewClass()}) this.${binding.getTarget().fieldName})"
74134a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                                }
742e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar                                val bindingCode = binding.toJavaCode(fieldName)
74397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                if (binding.getMinApi() > 1) {
7444c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                                    tab("if(getBuildSdkInt() >= ${binding.getMinApi()}) {") {
74597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                        tab("$bindingCode;")
74697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    }
74797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("}")
74897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                } else {
74997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                    tab("$bindingCode;")
75097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                                }
751d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                            }
75220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }
75320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        tab("}")
75420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    }
75520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount
75620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount            layoutBinder.getSortedTargets().filter { it.isUsed() }
75720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .flatMap { it.getBindings() }
75820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .filter { it.requiresOldValue() }
75920c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .groupBy { it.getExpr() }
76020c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                    .forEach {
76120c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        val flagSet = it.key.dirtyFlagSet
76220c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        tab("if (${tmpDirtyFlags.mapOr(flagSet) { suffix, index ->
76320c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
76420c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }.joinToString(" || ")
76520c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                        }) {") {
76620c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                            it.value.first().getComponentExpressions().forEach { expr ->
76720c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                                tab("this.${expr.oldValueName} = ${expr.toCode(false).generate()};")
76820c7182163d99575d382e065f5a5fe45ed6b87e2George Mount                            }
769d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
770d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        tab("}")
771d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
7725bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar            includedBinders.filter{it.isUsed()}.forEach { binder ->
7734c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount                tab("${binder.fieldName}.executePendingBindings();")
7747551861a29997eac7eaf6318e4d9f1cebd8b81d6Yigit Boyar            }
77596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{
776de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                it.isUsed() && it.getResolvedType() != null && it.getResolvedType().extendsViewStub()
777de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }.forEach {
778de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("if (${it.fieldName}.getBinding() != null) {") {
779de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                    tab("${it.fieldName}.getBinding().executePendingBindings();")
780de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                }
781de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("}")
782de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            }
783d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
7840fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar        nl("}")
785d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
786d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
787d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar    fun readWithDependants(expr : Expr, mJustRead : MutableList<Expr>, batch : MutableList<Expr>,
788d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tmpDirtyFlags : FlagSet, inheritedFlags : FlagSet? = null) : KCode = kcode("") {
789d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        mJustRead.add(expr)
790b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar        L.d("%s / readWithDependants %s", className, expr.getUniqueKey());
791d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        val flagSet = expr.shouldReadFlagSet
792d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val needsIfWrapper = inheritedFlags == null || !flagSet.bitsEqual(inheritedFlags)
793b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar        L.d("flag set:%s . inherited flags: %s. need another if: %s", flagSet, inheritedFlags, needsIfWrapper);
794d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val ifClause = "if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index ->
79543596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0"
79643596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.joinToString(" || ")
797d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        })"
798d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar
799d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        val readCode = kcode("") {
800e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar            if (expr.canBeEvaluatedToAVariable() && !expr.isVariable()) {
801d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // it is not a variable read it.
802d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                tab("// read ${expr.getUniqueKey()}")
803d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                // create an if case for all dependencies that might be null
804d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                val nullables = expr.getDependencies().filter {
805e6c6d3bf4fac3fa11c5780cfd3bc14cdb0caaea1George Mount                    it.isMandatory() && it.getOther().getResolvedType().isNullable()
80674f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar                }.map { it.getOther() }
807d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                if (!expr.isEqualityCheck() && nullables.isNotEmpty()) {
808019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab ("if ( ${nullables.map { "${it.executePendingLocalName} != null" }.joinToString(" && ")}) {") {
809019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                        tab("${expr.executePendingLocalName}").app(" = ", expr.toCode(true)).app(";")
810d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
811d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    tab("}")
812d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                } else {
813019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("${expr.executePendingLocalName}").app(" = ", expr.toCode(true)).app(";")
814d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8157920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                if (expr.isObservable()) {
816019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("updateRegistration(${expr.getId()}, ${expr.executePendingLocalName});")
817d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8180fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            }
819d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
8200fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            // if I am the condition for an expression, set its flag
8210fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            val conditionals = expr.getDependants().filter { !it.isConditional()
8220fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    && it.getDependant() is TernaryExpr && (it.getDependant() as TernaryExpr).getPred() == expr }
8230fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    .map { it.getDependant() }
8240fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar            if (conditionals.isNotEmpty()) {
8250fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("// setting conditional flags")
826019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                tab("if (${expr.executePendingLocalName}) {") {
8270fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8280fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(true)
8290fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8300fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
831d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                        }
832d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    }
833d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
8340fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                tab("} else {") {
8350fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    conditionals.forEach {
8360fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        val set = it.getRequirementFlagSet(false)
8370fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        mDirtyFlags.mapOr(set) { suffix , index ->
8380fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                            tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};")
8390fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                        }
8400fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                    }
8410fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar                } tab("}")
842d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
8430fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar
844d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            val chosen = expr.getDependants().filter {
845d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val dependant = it.getDependant()
846d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                batch.contains(dependant) &&
847d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadFlagSet.andNot(flagSet).isEmpty() &&
848d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                        dependant.shouldReadNow(mJustRead)
849d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
850d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            if (chosen.isNotEmpty()) {
851d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                val nextInheritedFlags = if (needsIfWrapper) flagSet else inheritedFlags
852d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                chosen.forEach {
853d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                    nl(readWithDependants(it.getDependant(), mJustRead, batch, tmpDirtyFlags, nextInheritedFlags))
854d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                }
855d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
856d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
857d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        if (needsIfWrapper) {
858d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab(ifClause) {
859d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                app(" {")
860d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar                nl(readCode)
861d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            }
862d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            tab("}")
863d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        } else {
864d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar            nl(readCode)
865d8c8ec27ed2ec0b11fa37f476395ce27834471f0Yigit Boyar        }
866d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
86743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar
868dea555cf42dc3583604699c8c018d22681f56166George Mount    fun declareFactories() = kcode("") {
869081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
870081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount            tab("return android.databinding.DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot);")
871081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        }
872081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount        nl("}")
87396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        if (!layoutBinder.isMerge()) {
874081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount            nl("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
8759bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount                tab("return bind(inflater.inflate(${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false));")
87696e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
87796e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
87896e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("public static ${baseClassName} bind(android.view.View view) {") {
87996e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("if (!\"${layoutBinder.getTag()}_0\".equals(view.getTag())) {") {
880f80b08430f11515ff944f89006799f21545602b9George Mount                    tab("throw new RuntimeException(\"view tag isn't correct on view:\" + view.getTag());")
88196e1c821dd446d1ed78f8ae61131550588f60a24George Mount                }
88296e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("}")
88396e1c821dd446d1ed78f8ae61131550588f60a24George Mount                tab("return new ${baseClassName}(view);")
88496e1c821dd446d1ed78f8ae61131550588f60a24George Mount            }
88596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            nl("}")
886dea555cf42dc3583604699c8c018d22681f56166George Mount        }
887dea555cf42dc3583604699c8c018d22681f56166George Mount    }
888dea555cf42dc3583604699c8c018d22681f56166George Mount
8894c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public fun writeBaseClass() : String =
89043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        kcode("package ${layoutBinder.getPackage()};") {
891fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.Bindable;")
892fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.DataBindingUtil;")
893fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            nl("import android.databinding.ViewDataBinding;")
8944c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("public abstract class ${baseClassName} extends ViewDataBinding {")
89596e1c821dd446d1ed78f8ae61131550588f60a24George Mount            layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
896de38dd3ef0577d25b2d59863603abe5750d0c231George Mount                tab("public final ${it.interfaceType} ${it.fieldName};")
89734a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
89834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            nl("")
89934a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab("protected ${baseClassName}(android.view.View root_, int localFieldCount") {
90096e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
901019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab(", ${it.interfaceType} ${it.constructorParamName}")
90234a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
90334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            }
90434a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            tab(") {") {
90534a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                tab("super(root_, localFieldCount);")
90696e1c821dd446d1ed78f8ae61131550588f60a24George Mount                layoutBinder.getSortedTargets().filter{it.getId() != null}.forEach {
907019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("this.${it.fieldName} = ${it.constructorParamName};")
90834a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount                }
9094c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9104c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9114c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            nl("")
91243596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            variables.forEach {
91318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                if (it.getUserDefinedType() != null) {
914895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                    val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
915019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar                    tab("public abstract void ${it.setterName}(${type} ${it.readableName});")
91618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount                }
91743596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
9189bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
919081ec223f1f2f801bd907ec6344b0c6aeee133e5George Mount                tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, attachToRoot);")
92043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            }
9214c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9229bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount            tab("public static ${baseClassName} inflate(android.view.LayoutInflater inflater) {") {
9239bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount                tab("return DataBindingUtil.<${baseClassName}>inflate(inflater, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false);")
9244c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9254c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
9264c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("public static ${baseClassName} bind(android.view.View view) {") {
927ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount                tab("return (${baseClassName})bind(view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
9284c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            }
9294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount            tab("}")
93043596c2b2997e40b709627419732100d78a62ff0Yigit Boyar            nl("}")
93143596c2b2997e40b709627419732100d78a62ff0Yigit Boyar        }.generate()
932dea555cf42dc3583604699c8c018d22681f56166George Mount}
933