LayoutBinderWriter.kt revision 7551861a29997eac7eaf6318e4d9f1cebd8b81d6
123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck/* 223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Copyright (C) 2015 The Android Open Source Project 323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * you may not use this file except in compliance with the License. 523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * You may obtain a copy of the License at 623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * http://www.apache.org/licenses/LICENSE-2.0 723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Unless required by applicable law or agreed to in writing, software 823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * distributed under the License is distributed on an "AS IS" BASIS, 923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * See the License for the specific language governing permissions and 1123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * limitations under the License. 1223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck */ 1323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 1423b797ab5151eb2474f3bdd679f2f07bfd723042John Reckpackage com.android.databinding.writer 1523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 1623b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.LayoutBinder 1723b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.expr.Expr 1823b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.ClassAnalyzer 193b20251a355c88193c439f928a84ae69483fb488John Reckimport kotlin.properties.Delegates 204f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckimport com.android.databinding.ext.joinToCamelCaseAsVar 21119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckimport com.android.databinding.BindingTarget 2223b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.expr.IdentifierExpr 2319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckimport com.android.databinding.util.Log 2465fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craikimport java.util.BitSet 2596a5c4c7bab6718524de7253da8309143ab48befChris Craikimport java.util.HashSet 2619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckimport com.android.databinding.util.L 274f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckimport org.apache.commons.lang3.NotImplementedException 2823b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.expr.ExprModel 2965fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craikimport com.android.databinding.writer.FlagSet 3065fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craikimport java.util.Arrays 3165fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craikimport java.lang 3265fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craikimport com.android.databinding.expr.TernaryExpr 33f47a594f5250b1914c36423ee6b371f0b8db09d0John Reckimport com.android.databinding.ext.androidId 34f47a594f5250b1914c36423ee6b371f0b8db09d0John Reckimport com.android.databinding.expr.FieldAccessExpr 35f47a594f5250b1914c36423ee6b371f0b8db09d0John Reckimport com.android.databinding.expr.ComparisonExpr 3623b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.expr.GroupExpr 3723b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.expr.MathExpr 3823b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.expr.MethodCallExpr 3923b797ab5151eb2474f3bdd679f2f07bfd723042John Reckimport com.android.databinding.expr.StaticIdentifierExpr 40119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckimport com.android.databinding.expr.SymbolExpr 41119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reckimport com.android.databinding.ext.androidId 423b20251a355c88193c439f928a84ae69483fb488John Reckimport com.android.databinding.ext.lazy 433b20251a355c88193c439f928a84ae69483fb488John Reckimport com.android.databinding.ext.br 444f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckimport com.android.databinding.ext.toJavaCode 451125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reckimport com.android.databinding.ext.isObservable 461125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reckimport com.android.databinding.expr.ResourceExpr 474f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckimport com.android.databinding.expr.BracketExpr 48d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik 49e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckfun Expr.isObservable() = com.android.databinding.ClassAnalyzer.getInstance().isObservable(this.getResolvedType()) 5051d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik 51ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckfun String.stripNonJava() = this.split("[^a-zA-Z0-9]").map{ it.trim() }.joinToCamelCaseAsVar() 52ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 53443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reckclass ExprModelExt { 5423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck val usedFieldNames = hashSetOf<String>() 5523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck val localizedFlags = arrayListOf<FlagSet>() 5623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 5717035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck fun localizeFlag(set : FlagSet, name:String) : FlagSet { 58443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck localizedFlags.add(set) 594f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck val result = getUniqueFieldName(name) 604f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck set.setLocalName(result) 6117035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck return set 6217035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck } 63d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik 6417035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck fun getUniqueFieldName(base : String) : String { 6517035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck var candidate = base 66e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck var i = 0 674f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck while (usedFieldNames.contains(candidate)) { 684f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck i ++ 69d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik candidate = base + i 704f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck } 7123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck usedFieldNames.add(candidate) 7223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck return candidate 73a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck } 74fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck} 75fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck 76a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckval ExprModel.ext by Delegates.lazy { (target : ExprModel) -> 77a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck ExprModelExt() 7823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} 793b20251a355c88193c439f928a84ae69483fb488John Reck 8023b797ab5151eb2474f3bdd679f2f07bfd723042John Reckfun ExprModel.getUniqueFieldName(base : String) : String = ext.getUniqueFieldName(base) 8123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 8223b797ab5151eb2474f3bdd679f2f07bfd723042John Reckfun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base) 8323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 843b20251a355c88193c439f928a84ae69483fb488John Reckval BindingTarget.readableUniqueName by Delegates.lazy {(target: BindingTarget) -> 8523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck val stripped = target.getId().androidId().stripNonJava() 8623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck target.getModel().ext.getUniqueFieldName(stripped) 8723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} 881125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck 891125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reckval BindingTarget.fieldName by Delegates.lazy { (target : BindingTarget) -> 904f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck "m${target.readableUniqueName.capitalize()}" 91dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck} 92368cdd85268999997fb495cf90c4417221797de0John Reck 93368cdd85268999997fb495cf90c4417221797de0John Reckval BindingTarget.getterName by Delegates.lazy { (target : BindingTarget) -> 944f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck "get${target.readableUniqueName.capitalize()}" 954f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck} 964f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck 974f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckval BindingTarget.androidId by Delegates.lazy { (target : BindingTarget) -> 982cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck "R.id.${target.getId().androidId()}" 99d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik} 1002cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck 1014f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckval Expr.readableUniqueName by Delegates.lazy { (expr : Expr) -> 1024f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck Log.d { "readableUniqueName for ${expr.getUniqueKey()}" } 1034f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck val stripped = "${expr.getUniqueKey().stripNonJava()}" 104f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck expr.getModel().ext.getUniqueFieldName(stripped) 105f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck} 106f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck 107dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reckval Expr.fieldName by Delegates.lazy { (expr : Expr) -> 1084f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck "m${expr.readableUniqueName.capitalize()}" 1094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck} 1101125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck 1111125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reckval Expr.hasFlag by Delegates.lazy { (expr : Expr) -> 1121125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck expr.getId() < expr.getModel().getInvalidateableFieldLimit() 1131125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck} 114a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck 1154f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckval Expr.localName by Delegates.lazy { (expr : Expr) -> 1162cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck if(expr.isVariable()) expr.fieldName else "${expr.readableUniqueName}" 1173b20251a355c88193c439f928a84ae69483fb488John Reck} 1184f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck 1194f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckval Expr.setterName by Delegates.lazy { (expr : Expr) -> 1204f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck "set${expr.readableUniqueName.capitalize()}" 1214f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck} 122a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck 1234f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckval Expr.onChangeName by Delegates.lazy { (expr : Expr) -> 124f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck "onChange${expr.readableUniqueName.capitalize()}" 125f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck} 1269fb42f07784ac9e1ab29fa7d5bcda6c3081d238fJohn Reck 12701a5ea35fbba4c5bb1d7790ae1677a2fa752e042John Reckval Expr.getterName by Delegates.lazy { (expr : Expr) -> 1284f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck "get${expr.readableUniqueName.capitalize()}" 1294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck} 130284b24358410cb0200e525a5ba36994090c83f20Chris Craik 13164bb413a664001c95c8439cf097dc3033f4ed733Andreas Gampeval Expr.staticFieldName by Delegates.lazy { (expr : Expr) -> 13264bb413a664001c95c8439cf097dc3033f4ed733Andreas Gampe "s${expr.readableUniqueName.capitalize()}" 1334f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck} 134058fc640017c90120c599d378a4cbc55668b05b7Chris Craik 1354f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckval Expr.dirtyFlagName by Delegates.lazy { (expr : Expr) -> 1364f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck "sFlag${expr.readableUniqueName.capitalize()}" 13763a06673253914510bbeebd500655008682dade1John Reck} 13863a06673253914510bbeebd500655008682dade1John Reck 13963a06673253914510bbeebd500655008682dade1John Reckval Expr.shouldReadFlagName by Delegates.lazy { (expr : Expr) -> 14063a06673253914510bbeebd500655008682dade1John Reck "sFlagRead${expr.readableUniqueName.capitalize()}" 141860d155f866cc15a725e7ce03763280987f24901John Reck} 142dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck 143dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reckval Expr.invalidateFlagName by Delegates.lazy { (expr : Expr) -> 1443b20251a355c88193c439f928a84ae69483fb488John Reck "sFlag${expr.readableUniqueName.capitalize()}Invalid" 145860d155f866cc15a725e7ce03763280987f24901John Reck} 146860d155f866cc15a725e7ce03763280987f24901John Reck 14768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckval Expr.conditionalFlagPrefix by Delegates.lazy { (expr : Expr) -> 14868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck "sFlag${expr.readableUniqueName.capitalize()}Is" 149d72e0a339b54af0c4e731513bbad120dff694723John Reck} 150d72e0a339b54af0c4e731513bbad120dff694723John Reck 151d72e0a339b54af0c4e731513bbad120dff694723John Reck 15219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckfun Expr.toCode(full : Boolean = false) : KCode { 15319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck val it = this 15419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck if (isDynamic() && !full) { 155ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck return kcode(localName) 156f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck } 15718f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck return when (it) { 158ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck is ComparisonExpr -> kcode("") { 159ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck app("", it.getLeft().toCode()) 160ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck app(it.getOp()) 161ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck app("", it.getRight().toCode()) 162e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck } 16325fbb3fa1138675379102a44405852555cefccbdJohn Reck is FieldAccessExpr -> kcode("") { 164998a6d81896df8b662cc10ddeb35087b78b38d72John Reck app("", it.getParent().toCode()) 165998a6d81896df8b662cc10ddeb35087b78b38d72John Reck if (it.getGetter().type == com.android.databinding.ClassAnalyzer.Callable.Type.FIELD) { 166998a6d81896df8b662cc10ddeb35087b78b38d72John Reck app(".", it.getGetter().name) 167ec845a215e343cdb3b2e4c7b6aff7b24beb0236bJohn Reck } else { 168e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck app(".", it.getGetter().name).app("()") 169119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck } 170e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck } 171998a6d81896df8b662cc10ddeb35087b78b38d72John Reck is GroupExpr -> kcode("(").app("", it.getWrapped().toCode()).app(")") 172998a6d81896df8b662cc10ddeb35087b78b38d72John Reck is StaticIdentifierExpr -> kcode(it.getResolvedType().toJavaCode()) 173998a6d81896df8b662cc10ddeb35087b78b38d72John Reck is IdentifierExpr -> kcode(it.localName) 174998a6d81896df8b662cc10ddeb35087b78b38d72John Reck is MathExpr -> kcode("") { 175aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck app("", it.getLeft().toCode()) 176aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck app(it.getOp()) 177aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck app("", it.getRight().toCode()) 178aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck } 179aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck is MethodCallExpr -> kcode("") { 180a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck app("", it.getTarget().toCode()) 181a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck app(".", it.getGetter().name) 182a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck app("(") 183a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck var first = true 184a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck it.getArgs().forEach { 185a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck apps(if (first) "" else ",", it.toCode()) 186a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck first = false 187a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck } 188a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck app(")") 189cd028f336e36b22dbe8cf623eb5bd2361314495cJohn Reck } 190f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck is SymbolExpr -> kcode(it.getText()) // TODO 191f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck is TernaryExpr -> kcode("") { 192f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck app("", it.getPred().toCode()) 193f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck app("?", it.getIfTrue().toCode()) 194e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck app(":", it.getIfFalse().toCode()) 195e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck } 196e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck is ResourceExpr -> kcode("") { 197f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck app("", it.toJava()) 198f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck } 199f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck is BracketExpr -> kcode("") { 200f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck app("", it.getTarget().toCode()) 201a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck val bracketType = it.getAccessor(); 202a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck when (bracketType) { 203a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck BracketExpr.BracketAccessor.ARRAY -> { 204a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck app("[", it.getArg().toCode()) 205a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck app("]") 206e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck } 2074f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck BracketExpr.BracketAccessor.LIST -> { 208a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik app(".get(") 2094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck if (it.argCastsInteger()) { 210fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck app("(Integer)") 211ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 212fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck app("", it.getArg().toCode()) 213e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck app(")") 214e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck } 215e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck BracketExpr.BracketAccessor.MAP -> { 2164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck app(".get(", it.getArg().toCode()) 2173b20251a355c88193c439f928a84ae69483fb488John Reck app(")") 2184f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck } 2194f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck } 220e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck } 2211125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck else -> kcode("//NOT IMPLEMENTED YET") 222e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck } 223fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck 2245cdb8f998c58a2226112b36e4c391866346e5e17John Reck} 2250a97330b98dd633b58dcfff405d94476c89e867dJohn Reck 2260a97330b98dd633b58dcfff405d94476c89e867dJohn Reckfun Expr.isVariable() = this is IdentifierExpr && this.isDynamic() 2270a97330b98dd633b58dcfff405d94476c89e867dJohn Reck 2280a97330b98dd633b58dcfff405d94476c89e867dJohn Reckfun Expr.conditionalFlagName(output : Boolean, suffix : String) = "${dirtyFlagName}_${output}$suffix" 229e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck 2304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck 2314f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckval Expr.dirtyFlagSet by Delegates.lazy { (expr : Expr) -> 232e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck val fs = FlagSet(expr.getInvalidFlags(), expr.getModel().getFlagBucketCount()) 233107843de4507b3511006cb9c77b8d0364374385aTom Hudson expr.getModel().localizeFlag(fs, expr.dirtyFlagName) 234e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck} 2354f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck 236107843de4507b3511006cb9c77b8d0364374385aTom Hudsonval Expr.invalidateFlagSet by Delegates.lazy { (expr : Expr) -> 2374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck val fs = FlagSet(expr.getId()) 2384f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck expr.getModel().localizeFlag(fs, expr.invalidateFlagName) 2394f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck} 240107843de4507b3511006cb9c77b8d0364374385aTom Hudson 2414f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckval Expr.shouldReadFlagSet by Delegates.lazy { (expr : Expr) -> 242fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck val fs = FlagSet(expr.getShouldReadFlags(), expr.getModel().getFlagBucketCount()) 2434f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck expr.getModel().localizeFlag(fs, expr.shouldReadFlagName) 244107843de4507b3511006cb9c77b8d0364374385aTom Hudson} 2454f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck 246fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckval Expr.conditionalFlags by Delegates.lazy { (expr : Expr) -> 247fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck val model = expr.getModel() 248ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck arrayListOf(model.localizeFlag(FlagSet(expr.getRequirementFlagIndex(false)), 249ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck "${expr.conditionalFlagPrefix}False"), 250ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck model.localizeFlag(FlagSet(expr.getRequirementFlagIndex(true)), 251ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck "${expr.conditionalFlagPrefix}True")) 252107843de4507b3511006cb9c77b8d0364374385aTom Hudson} 2534f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck 2540e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reckfun Expr.getRequirementFlagSet(expected : Boolean) : FlagSet = conditionalFlags[if(expected) 1 else 0] 2550e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck 25623b797ab5151eb2474f3bdd679f2f07bfd723042John Reckfun FlagSet.notEmpty(cb : (suffix : String, value : Long) -> Unit) { 257fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck buckets.withIndex().forEach { 258ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck if (it.value != 0L) { 259ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck cb(getWordSuffix(it.index), buckets[it.index]) 260ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 261fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck } 26223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} 26323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck 264e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckfun FlagSet.getBitSuffix(bitIndex : Int) : String { 26518f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck val word = bitIndex / FlagSet.sBucketSize 266368cdd85268999997fb495cf90c4417221797de0John Reck return getWordSuffix(word) 267368cdd85268999997fb495cf90c4417221797de0John Reck} 268368cdd85268999997fb495cf90c4417221797de0John Reck 269368cdd85268999997fb495cf90c4417221797de0John Reckfun FlagSet.getWordSuffix(wordIndex : Int) : String { 270e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck return if(wordIndex == 0) "" else "_${wordIndex}" 271e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck} 272fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck 273ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckfun FlagSet.localValue(bucketIndex : Int) = 274ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck if (getLocalName() == null) buckets[bucketIndex] 275ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck else "${getLocalName()}${getWordSuffix(bucketIndex)}" 276ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 277ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckfun FlagSet.or(other : FlagSet, cb : (suffix : String) -> Unit) { 278fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck val min = Math.min(buckets.size(), other.buckets.size()) 2793b20251a355c88193c439f928a84ae69483fb488John Reck for (i in 0..(min - 1)) { 280ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck // if these two can match by any chance, call the callback 281a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck if (intersect(other, i)) { 282e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck cb(getWordSuffix(i)) 283a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck } 284e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck } 285e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck} 2863b20251a355c88193c439f928a84ae69483fb488John Reck 287d3d8dafc2f61fb118c060720b52684c59303f3dbJohn Reckfun <T> FlagSet.mapOr(other : FlagSet, cb : (suffix : String, index : Int) -> T) : List<T> { 2880d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck val min = Math.min(buckets.size(), other.buckets.size()) 2893b20251a355c88193c439f928a84ae69483fb488John Reck val result = arrayListOf<T>() 2903b20251a355c88193c439f928a84ae69483fb488John Reck for (i in 0..(min - 1)) { 2910d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck // if these two can match by any chance, call the callback 2920d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck if (intersect(other, i)) { 2936f07a0dc875a9eac67312085a8e0133b9e2f4771John Reck result.add(cb(getWordSuffix(i), i)) 294d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik } 29523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck } 29623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck return result 297998a6d81896df8b662cc10ddeb35087b78b38d72John Reck} 298998a6d81896df8b662cc10ddeb35087b78b38d72John Reck 299d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craikclass LayoutBinderWriter(val layoutBinder : LayoutBinder) { 300998a6d81896df8b662cc10ddeb35087b78b38d72John Reck val model = layoutBinder.getModel() 301998a6d81896df8b662cc10ddeb35087b78b38d72John Reck val mDirtyFlags by Delegates.lazy { 302998a6d81896df8b662cc10ddeb35087b78b38d72John Reck val fs = FlagSet(BitSet(), model.getFlagBucketCount()); 303998a6d81896df8b662cc10ddeb35087b78b38d72John Reck Arrays.fill(fs.buckets, -1) 304998a6d81896df8b662cc10ddeb35087b78b38d72John Reck fs.setDynamic(true) 305998a6d81896df8b662cc10ddeb35087b78b38d72John Reck model.localizeFlag(fs, "mDirtyFlags") 306d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik fs 307998a6d81896df8b662cc10ddeb35087b78b38d72John Reck } 308998a6d81896df8b662cc10ddeb35087b78b38d72John Reck 309998a6d81896df8b662cc10ddeb35087b78b38d72John Reck val dynamics by Delegates.lazy { model.getExprMap().values().filter { it.isDynamic() } } 310998a6d81896df8b662cc10ddeb35087b78b38d72John Reck val className = layoutBinder.getClassName() 311998a6d81896df8b662cc10ddeb35087b78b38d72John Reck 312998a6d81896df8b662cc10ddeb35087b78b38d72John Reck val identifiers by Delegates.lazy { 313998a6d81896df8b662cc10ddeb35087b78b38d72John Reck dynamics.filter { it is IdentifierExpr } 314998a6d81896df8b662cc10ddeb35087b78b38d72John Reck } 315998a6d81896df8b662cc10ddeb35087b78b38d72John Reck 316998a6d81896df8b662cc10ddeb35087b78b38d72John Reck val interfaceName = "${layoutBinder.getInterfaceName()}" 3173e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck 3183e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck val includedBinders by Delegates.lazy { 3193e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck layoutBinder.getBindingTargets().filter { it.isBinder() } 3203e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck } 3213e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck 3223e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck val variables by Delegates.lazy { 3233e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck model.getExprMap().values().filterIsInstance(javaClass<IdentifierExpr>()).filter { it.isVariable() } 3243e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck } 3253e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck 3263e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck public fun write() : String = 3273e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck kcode("package ${layoutBinder.getPackage()};") { 3283e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck nl("import ${layoutBinder.getProjectPackage()}.R;") 3299eb9f6f8cbbbd87d45da8071aa54cb066a797723John Reck nl("import android.view.View;") 3303e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck nl("public class ${className} extends com.android.databinding.library.ViewDataBinder implements ${interfaceName} {") { 3313e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck tab(declareViews()) 3323e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck tab(declareVariables()) 3333e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck tab(declareConstructor()) 3343e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck tab(declareInvalidateAll()) 3353e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck tab(declareLog()) 3363e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck tab(declareSetVariable()) 337443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck tab(variableSettersAndGetters()) 3383e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck tab(viewGetters()) 339998a6d81896df8b662cc10ddeb35087b78b38d72John Reck tab(onFieldChange()) 340d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik 341998a6d81896df8b662cc10ddeb35087b78b38d72John Reck tab(rebindDirty()) 3423e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck 3433e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck tab(declareDirtyFlags()) 34419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck } 34519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck nl("}") 34668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck tab(flagMapping()) 3473b20251a355c88193c439f928a84ae69483fb488John Reck tab("//end") 34819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck }.generate() 34919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck 350f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck fun declareConstructor() = kcode("") { 351f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck nl("public ${className}(View root) {") { 3523b20251a355c88193c439f928a84ae69483fb488John Reck tab("super(root, ${model.getObservables().size()});") 353e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck layoutBinder.getBindingTargets().forEach { 354dff9957cc22a1174a4cf91de6609c50934d29434John Reck if (it.isBinder()) { 355dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck tab("this.${it.fieldName} = com.android.databinding.library.DataBinder.createBinder(root.findViewById(${it.androidId}), R.layout.${it.getIncludedLayout()});") 356f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck } else { 357f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck tab("this.${it.fieldName} = (${it.getViewClass()}) root.findViewById(${it.androidId});") 358f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck } 359f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck } 360f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck tab("invalidateAll();"); 361f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck } 362f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck nl("}") 363f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck } 364786afcb3eec18315ec54987a08814ff28f13d09fJorim Jaggi 3653c2b7fa8c584c5ed56f1bd6ad53f2e87f0a6eb44John Reck fun declareInvalidateAll() = kcode("") { 366f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck nl("@Override") 367f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck nl("public void invalidateAll() {") { 368f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck val bs = BitSet() 369f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck bs.set(0, model.getInvalidateableFieldLimit()) 370f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck val fs = FlagSet(bs, mDirtyFlags.buckets.size()) 371e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck for (i in (0..(mDirtyFlags.buckets.size() - 1))) { 372e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};") 373e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck } 374fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck includedBinders.forEach { binder -> 37519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck tab("${binder.fieldName}.invalidateAll();") 37619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck } 37719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck } 37819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck nl("}") 3791949e7928eeec22cd3f74b5f763a4eb433238453John Reck } 380f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck 3813b20251a355c88193c439f928a84ae69483fb488John Reck fun declareSetVariable() = kcode("") { 3821949e7928eeec22cd3f74b5f763a4eb433238453John Reck nl("public boolean setVariable(int variableId, Object variable) {") { 3831949e7928eeec22cd3f74b5f763a4eb433238453John Reck tab("switch(variableId) {") { 38419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck variables.forEach { 385f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck tab ("case ${it.getName().br()} :") { 386fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck tab("${it.setterName}((${it.getResolvedType().toJavaCode()}) variable);") 387fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck tab("return true;") 3883b20251a355c88193c439f928a84ae69483fb488John Reck } 3893b20251a355c88193c439f928a84ae69483fb488John Reck } 3903b20251a355c88193c439f928a84ae69483fb488John Reck } 39166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck tab("}") 39266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck tab("return false;") 393ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 394ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck nl("}") 395ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 396ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 397ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck fun declareLog() = kcode("") { 398ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck nl("private void log(String msg, long i) {") { 399ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck tab("""android.util.Log.d("BINDER", msg + ":" + Long.toHexString(i));""") 400ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 401ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck nl("}") 402ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 403ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck 404ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck fun variableSettersAndGetters() = kcode("") { 405ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck variables.forEach { 406ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck nl("public void ${it.setterName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}) {") { 407ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck if (it.isObservable()) { 408ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck tab("updateRegistration(${it.getId()}, ${it.readableUniqueName});"); 409ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck } 410ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck tab("this.${it.fieldName} = ${it.readableUniqueName};") 411ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck // set dirty flags! 412ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck val flagSet = it.invalidateFlagSet 413ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck mDirtyFlags.mapOr(flagSet) { suffix, index -> 414ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};") 41523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck } 41623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck tab("super.requestRebind();") 41723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck } 418 nl("}") 419 nl("") 420 nl("public ${it.getResolvedType().toJavaCode()} ${it.getterName}() {") { 421 tab("return ${it.fieldName};") 422 } 423 nl("}") 424 } 425 } 426 427 fun onFieldChange() = kcode("") { 428 tab("@Override") 429 tab("protected boolean onFieldChange(int mLocalFieldId, Object object, int fieldId) {") { 430 tab("switch (mLocalFieldId) {") { 431 model.getObservables().forEach { 432 tab("case ${it.getId()} :") { 433 tab("return ${it.onChangeName}((${it.getResolvedType().toJavaCode()}) object, fieldId);") 434 } 435 } 436 } 437 tab("}") 438 tab("return false;") 439 } 440 tab("}") 441 442 model.getObservables().forEach { 443 tab("private boolean ${it.onChangeName}(${it.getResolvedType().toJavaCode()} ${it.readableUniqueName}, int fieldId) {") { 444 tab("switch (fieldId) {", { 445 val accessedFields: List<FieldAccessExpr> = it.getParents().filterIsInstance(javaClass<FieldAccessExpr>()) 446 accessedFields.filter { it.canBeInvalidated() } 447 .groupBy { it.getName() } 448 .forEach { 449 tab("case ${it.key.br()}:") { 450 val field = it.value.first() 451 mDirtyFlags.mapOr(field.invalidateFlagSet) { suffix, index -> 452 tab("${mDirtyFlags.localValue(index)} |= ${field.invalidateFlagSet.localValue(index)};") 453 } 454 tab("return true;") 455 } 456 457 } 458 tab("case ${"".br()}:") { 459 val flagSet = it.invalidateFlagSet 460 mDirtyFlags.mapOr(flagSet) { suffix, index -> 461 tab("${mDirtyFlags.getLocalName()}$suffix |= ${flagSet.localValue(index)};") 462 } 463 tab("return true;") 464 } 465 466 }) 467 tab("}") 468 tab("return false;") 469 } 470 tab("}") 471 } 472 } 473 474 fun declareViews() = kcode("// views") { 475 layoutBinder.getBindingTargets().forEach { 476 nl("private ${it.getViewClass()} ${it.fieldName};") 477 } 478 } 479 480 fun viewGetters() = kcode("// view getters") { 481 layoutBinder.getBindingTargets().forEach { 482 nl("@Override") 483 nl("public ${it.getViewClass()} ${it.getterName}() {") { 484 tab("return ${it.fieldName};") 485 } 486 nl("}") 487 } 488 } 489 490 fun declareVariables() = kcode("// variables") { 491 variables.forEach { 492 nl("private ${it.getResolvedType().toJavaCode()} ${it.fieldName};") 493 } 494 } 495 496 fun declareDirtyFlags() = kcode("// dirty flag") { 497 model.ext.localizedFlags.forEach { flag -> 498 flag.notEmpty { (suffix, value) -> 499 nl("private") 500 app(" ", if(flag.isDynamic()) null else "static final"); 501 app(" ", " ${flag.type} ${flag.getLocalName()}$suffix = $value;") 502 } 503 } 504 } 505 506 fun flagMapping() = kcode("/* flag mapping") { 507 if (model.getFlagMapping() != null) { 508 val mapping = model.getFlagMapping() 509 for (i in mapping.indices) { 510 tab("flag $i: ${mapping[i]}") 511 } 512 } 513 nl("flag mapping end*/") 514 } 515 516 fun rebindDirty() = kcode("") { 517 nl("@Override") 518 nl("public void rebindDirty() {") { 519 val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets) 520 tmpDirtyFlags.setLocalName("dirtyFlags"); 521 for (i in (0..mDirtyFlags.buckets.size() - 1)) { 522 tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};") 523 tab("${mDirtyFlags.localValue(i)} = 0;") 524 } 525 //tab("""log("dirty flags", mDirtyFlags);""") 526 model.getPendingExpressions().filterNot {it.isVariable()}.forEach { 527 tab("${it.getResolvedType().toJavaCode()} ${it.localName} = ${it.getDefaultValue()};") 528 } 529 530 do { 531 val batch = model.filterShouldRead(model.getPendingExpressions()).toArrayList() 532 val mJustRead = arrayListOf<Expr>() 533 while (!batch.none()) { 534 val readNow = batch.filter { it.shouldReadNow(mJustRead) } 535 if (readNow.isEmpty()) { 536 throw IllegalStateException("do not know what I can read. bailing out ${batch.joinToString("\n")}") 537 } 538 Log.d { "new read now. batch size: ${batch.size()}, readNow size: ${readNow.size()}" } 539 540 readNow.forEach { 541 nl(readWithDependants(it, mJustRead, batch, tmpDirtyFlags)) 542 } 543 batch.removeAll(mJustRead) 544 } 545 tab("// batch finished") 546 } while(model.markBitsRead()) 547 548 // 549 layoutBinder.getBindingTargets() 550 .flatMap { it.getBindings() } 551 .groupBy { it.getExpr() } 552 .forEach { 553 val flagSet = it.key.dirtyFlagSet 554 tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index -> 555 "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0" 556 }.joinToString(" || ") 557 }) {") { 558 it.value.forEach { binding -> 559 tab("${binding.toJavaCode(binding.getTarget().fieldName, binding.getExpr().toCode().generate())};") 560 } 561 } 562 tab("}") 563 } 564 // 565 includedBinders.forEach { binder -> 566 tab("${binder.fieldName}.rebindDirty();") 567 } 568 } 569 nl("}") 570 571 } 572 573 fun readWithDependants(expr : Expr, mJustRead : MutableList<Expr>, batch : MutableList<Expr>, tmpDirtyFlags : FlagSet) : KCode = kcode("") { 574 mJustRead.add(expr) 575 Log.d { expr.getUniqueKey() } 576 val flagSet = expr.shouldReadFlagSet 577 tab("if (${tmpDirtyFlags.mapOr(flagSet){ suffix, index -> 578 "(${tmpDirtyFlags.localValue(index)} & ${flagSet.localValue(index)}) != 0" 579 }.joinToString(" || ") 580 }) {") { 581 if (!expr.isVariable()) { 582 // it is not a variable read it. 583 tab("// read ${expr.getUniqueKey()}") 584 // create an if case for all dependencies that might be null 585 val nullables = expr.getDependencies().filter { 586 it.isMandatory() && 587 ClassAnalyzer.isNullable(it.getOther().getResolvedType()) 588 } 589 .map { it.getOther() } 590 if (!expr.isEqualityCheck() && nullables.isNotEmpty()) { 591 tab ("if ( ${nullables.map { "${it.localName} != null" }.joinToString(" && ")}) {") { 592 tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";") 593 //tab("""log("${expr}" + ${expr.localName},0);""") 594 } 595 tab("}") 596 } else { 597 tab("${expr.localName}").app(" = ", expr.toCode(true)).app(";") 598 //tab("""log("${expr}" + ${expr.localName},0);""") 599 } 600 if (expr.getResolvedType().isObservable()) { 601 tab("updateRegistration(${expr.getId()}, ${expr.localName});") 602 } 603 } 604 605 // if I am the condition for an expression, set its flag 606 val conditionals = expr.getDependants().filter { !it.isConditional() 607 && it.getDependant() is TernaryExpr && (it.getDependant() as TernaryExpr).getPred() == expr } 608 .map { it.getDependant() } 609 if (conditionals.isNotEmpty()) { 610 tab("// setting conditional flags") 611 tab("if (${expr.localName}) {") { 612 conditionals.forEach { 613 val set = it.getRequirementFlagSet(true) 614 mDirtyFlags.mapOr(set) { suffix , index -> 615 tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};") 616 } 617 } 618 } 619 tab("} else {") { 620 conditionals.forEach { 621 val set = it.getRequirementFlagSet(false) 622 mDirtyFlags.mapOr(set) { suffix , index -> 623 tab("${tmpDirtyFlags.localValue(index)} |= ${set.localValue(index)};") 624 } 625 } 626 } tab("}") 627 } 628 629 val chosen = expr.getDependants().filter { 630 batch.contains(it.getDependant()) && it.getDependant().shouldReadNow(mJustRead) 631 } 632 if (chosen.isNotEmpty()) { 633 chosen.forEach { 634 nl(readWithDependants(it.getDependant(), mJustRead, batch, tmpDirtyFlags)) 635 } 636 } 637 } 638 tab("}") 639 } 640 641 public fun writeInterface() : String = 642 kcode("package ${layoutBinder.getPackage()};") { 643 nl("import android.binding.Bindable;") 644 nl("import com.android.databinding.library.IViewDataBinder;") 645 646 nl("public interface ${interfaceName} extends IViewDataBinder {") 647 variables.forEach { 648 tab("@Bindable") 649 tab("public void ${it.setterName}(${it.getUserDefinedType()} ${it.readableUniqueName});") 650 } 651 layoutBinder.getBindingTargets().forEach { 652 tab("public ${it.getViewClass()} ${it.getterName}();") 653 } 654 nl("}") 655 }.generate() 656}