1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.databinding.tool.expr; 18 19import android.databinding.tool.reflection.ModelAnalyzer; 20import android.databinding.tool.reflection.ModelClass; 21import android.databinding.tool.solver.ExecutionPath; 22import android.databinding.tool.writer.KCode; 23 24import java.util.ArrayList; 25import java.util.List; 26 27/** 28 * This is used by inverse field access expressions to assign back to the field. 29 * For example, <code>@={a.b}</code> is inverted to @{code a.b = value;} 30 */ 31public class FieldAssignmentExpr extends Expr { 32 final String mName; 33 34 public FieldAssignmentExpr(Expr target, String name, Expr value) { 35 super(target, value); 36 mName = name; 37 } 38 39 @Override 40 protected String computeUniqueKey() { 41 return join(getTarget().getUniqueKey(), mName, "=", getValueExpr().getUniqueKey()); 42 } 43 44 public Expr getTarget() { 45 return (FieldAccessExpr) getChildren().get(0); 46 } 47 48 public Expr getValueExpr() { 49 return getChildren().get(1); 50 } 51 52 @Override 53 protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) { 54 return modelAnalyzer.findClass(void.class); 55 } 56 57 @Override 58 protected List<Dependency> constructDependencies() { 59 return constructDynamicChildrenDependencies(); 60 } 61 62 @Override 63 protected KCode generateCode() { 64 return new KCode() 65 .app("", getTarget().toCode()) 66 .app("." + mName + " = ", getValueExpr().toCode()); 67 } 68 69 @Override 70 public Expr cloneToModel(ExprModel model) { 71 return model.assignment(getTarget().cloneToModel(model), mName, getValueExpr()); 72 } 73 74 @Override 75 protected String getInvertibleError() { 76 return "Assignment expressions are inverses of field access expressions."; 77 } 78 79 @Override 80 public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) { 81 Expr child = getTarget(); 82 List<ExecutionPath> targetPaths = child.toExecutionPath(paths); 83 84 // after this, we need a null check. 85 List<ExecutionPath> result = new ArrayList<ExecutionPath>(); 86 if (child instanceof StaticIdentifierExpr) { 87 result.addAll(toExecutionPathInOrder(paths, child)); 88 } else { 89 for (ExecutionPath path : targetPaths) { 90 final ComparisonExpr cmp = getModel() 91 .comparison("!=", child, getModel().symbol("null", Object.class)); 92 path.addPath(cmp); 93 final ExecutionPath subPath = path.addBranch(cmp, true); 94 if (subPath != null) { 95 subPath.addPath(this); 96 result.add(subPath); 97 } 98 } 99 } 100 return result; 101 } 102 103 @Override 104 public String toString() { 105 return getTarget().toString() + '.' + mName + " = " + getValueExpr(); 106 } 107} 108