CallbackExprModel.java revision 6047998943beebd81e0ae1068df39c0cbee38628
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.processing.ScopedException; 226047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.store.Location; 236047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.util.L; 246047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.util.Preconditions; 256047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 266047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.ArrayList; 276047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.List; 286047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.Map; 296047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 306047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar/** 316047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * Callbacks are evaluated when event happens, not when execute pending is run. To separate their 326047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * expressions, we provide a separate model for them that extends the main model. This allows them 336047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar * to introduce their own variables etc. without mixing them with other expressions. 346047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar */ 356047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarpublic class CallbackExprModel extends ExprModel { 366047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // used for imports and other stuff. 376047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final ExprModel mOriginal; 386047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final List<CallbackArgExpr> mArguments = new ArrayList<CallbackArgExpr>(); 396047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public CallbackExprModel(ExprModel original) { 406047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mOriginal = original; 416047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 426047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 436047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 446047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public Map<String, String> getImports() { 456047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mOriginal.getImports(); 466047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 476047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 486047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 496047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public StaticIdentifierExpr addImport(String alias, String type, Location location) { 506047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mOriginal.addImport(alias, type, location); 516047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 526047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 536047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 546047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public <T extends Expr> T register(T expr) { 556047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // locations are only synced to main model so we need to sync overselves here. 566047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar setCurrentLocationInFile(mOriginal.getCurrentLocationInFile()); 576047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar setCurrentParserContext(mOriginal.getCurrentParserContext()); 586047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return super.register(expr); 596047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 606047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 616047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 626047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public void seal() { 636047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // ensure all types are calculated 646047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar for (Expr expr : mExprMap.values()) { 656047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar expr.getResolvedType(); 666047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar expr.markAsUsedInCallback(); 676047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 686047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar markSealed(); 696047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // we do not resolve dependencies for these expression because they are resolved via 706047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // ExecutionPath and should not interfere with the main expr model's dependency graph. 716047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 726047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 736047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Override 746047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public IdentifierExpr identifier(String name) { 756047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar CallbackArgExpr arg = findArgByName(name); 766047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (arg != null) { 776047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return arg; 786047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 796047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar IdentifierExpr id = new IdentifierExpr(name); 806047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final Expr existing = mExprMap.get(id.getUniqueKey()); 816047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (existing == null) { 826047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // this is not a method variable reference. register it in the main model 836047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final IdentifierExpr identifier = mOriginal.identifier(name); 846047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mExprMap.put(identifier.getUniqueKey(), identifier); 856047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar identifier.markAsUsedInCallback(); 866047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return identifier; 876047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 886047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return (IdentifierExpr) existing; 896047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 906047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 916047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private CallbackArgExpr findArgByName(String name) { 926047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar for (CallbackArgExpr arg : mArguments) { 936047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (name.equals(arg.getName())) { 946047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return arg; 956047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 966047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 976047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return null; 986047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 996047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1006047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public CallbackArgExpr callbackArg(String name) { 1016047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.checkNull(findArgByName(name), 1026047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar ErrorMessages.DUPLICATE_CALLBACK_ARGUMENT, name); 1036047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final CallbackArgExpr id = new CallbackArgExpr(mArguments.size(), name); 1046047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final CallbackArgExpr added = register(id); 1056047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mArguments.add(added); 1066047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1076047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar try { 1086047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Scope.enter(added); 1096047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar IdentifierExpr identifierWithSameName = mOriginal.findIdentifier(name); 1106047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (identifierWithSameName != null) { 1116047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar L.w(ErrorMessages.CALLBACK_VARIABLE_NAME_CLASH, name, name, 1126047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar identifierWithSameName.getUserDefinedType()); 1136047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1146047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } finally { 1156047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Scope.exit(); 1166047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1176047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return added; 1186047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1196047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1206047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public int getArgCount() { 1216047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mArguments.size(); 1226047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1236047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1246047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public List<CallbackArgExpr> getArguments() { 1256047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mArguments; 1266047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1276047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar} 128