16047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar/* 26047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * Copyright (C) 2016 The Android Open Source Project 36047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * 46047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 56047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * you may not use this file except in compliance with the License. 66047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * You may obtain a copy of the License at 76047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * 86047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 96047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * 106047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * Unless required by applicable law or agreed to in writing, software 116047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 126047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * See the License for the specific language governing permissions and 146047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * limitations under the License. 156047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar */ 166047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 176047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarpackage android.databinding.tool.expr; 186047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 196047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.processing.ErrorMessages; 206047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.processing.Scope; 216047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.store.Location; 226047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.util.L; 236047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.util.Preconditions; 246047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 256047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.ArrayList; 266047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.List; 276047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.Map; 286047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 296047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar/** 306047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * Callbacks are evaluated when event happens, not when execute pending is run. To separate their 316047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * expressions, we provide a separate model for them that extends the main model. This allows them 326047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * to introduce their own variables etc. without mixing them with other expressions. 336047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar */ 346047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarpublic class CallbackExprModel extends ExprModel { 356047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // used for imports and other stuff. 366047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final ExprModel mOriginal; 376047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final List<CallbackArgExpr> mArguments = new ArrayList<CallbackArgExpr>(); 386047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public CallbackExprModel(ExprModel original) { 396047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mOriginal = original; 406047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 416047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 426047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 436047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public Map<String, String> getImports() { 446047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mOriginal.getImports(); 456047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 466047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 476047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 486047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public StaticIdentifierExpr addImport(String alias, String type, Location location) { 496047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mOriginal.addImport(alias, type, location); 506047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 516047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 526047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 536047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public <T extends Expr> T register(T expr) { 546047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // locations are only synced to main model so we need to sync overselves here. 556047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar setCurrentLocationInFile(mOriginal.getCurrentLocationInFile()); 566047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar setCurrentParserContext(mOriginal.getCurrentParserContext()); 576047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return super.register(expr); 586047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 596047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 606047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 616047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public void seal() { 626047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // ensure all types are calculated 636047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar for (Expr expr : mExprMap.values()) { 646047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar expr.getResolvedType(); 656047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar expr.markAsUsedInCallback(); 666047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 676047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar markSealed(); 686047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // we do not resolve dependencies for these expression because they are resolved via 696047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // ExecutionPath and should not interfere with the main expr model's dependency graph. 706047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 716047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 726047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 736047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public IdentifierExpr identifier(String name) { 746047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar CallbackArgExpr arg = findArgByName(name); 756047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (arg != null) { 766047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return arg; 776047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 786047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar IdentifierExpr id = new IdentifierExpr(name); 796047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final Expr existing = mExprMap.get(id.getUniqueKey()); 806047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (existing == null) { 816047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // this is not a method variable reference. register it in the main model 826047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final IdentifierExpr identifier = mOriginal.identifier(name); 836047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mExprMap.put(identifier.getUniqueKey(), identifier); 846047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar identifier.markAsUsedInCallback(); 856047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return identifier; 866047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 876047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return (IdentifierExpr) existing; 886047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 896047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 906047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private CallbackArgExpr findArgByName(String name) { 916047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar for (CallbackArgExpr arg : mArguments) { 926047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (name.equals(arg.getName())) { 936047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return arg; 946047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 956047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 966047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return null; 976047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 986047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 996047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public CallbackArgExpr callbackArg(String name) { 1006047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.checkNull(findArgByName(name), 1016047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar ErrorMessages.DUPLICATE_CALLBACK_ARGUMENT, name); 1026047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final CallbackArgExpr id = new CallbackArgExpr(mArguments.size(), name); 1036047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final CallbackArgExpr added = register(id); 1046047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mArguments.add(added); 1056047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1066047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar try { 1076047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Scope.enter(added); 1086047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar IdentifierExpr identifierWithSameName = mOriginal.findIdentifier(name); 1096047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (identifierWithSameName != null) { 1106047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar L.w(ErrorMessages.CALLBACK_VARIABLE_NAME_CLASH, name, name, 1116047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar identifierWithSameName.getUserDefinedType()); 1126047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1136047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } finally { 1146047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Scope.exit(); 1156047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1166047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return added; 1176047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1186047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1196047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public int getArgCount() { 1206047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mArguments.size(); 1216047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1226047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1236047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public List<CallbackArgExpr> getArguments() { 1246047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mArguments; 1256047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1266047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar} 127