MethodCallExpr.java revision ec2f3896c21a504b464bf591cdb45b62692b6760
1/*
2 * Copyright (C) 2015 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 com.google.common.collect.Iterables;
20
21import android.databinding.tool.reflection.Callable;
22import android.databinding.tool.reflection.Callable.Type;
23import android.databinding.tool.reflection.ModelAnalyzer;
24import android.databinding.tool.reflection.ModelClass;
25import android.databinding.tool.reflection.ModelMethod;
26import android.databinding.tool.util.L;
27
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.List;
31import static android.databinding.tool.reflection.Callable.STATIC;
32import static android.databinding.tool.reflection.Callable.DYNAMIC;
33import static android.databinding.tool.reflection.Callable.CAN_BE_INVALIDATED;
34
35
36public class MethodCallExpr extends Expr {
37    final String mName;
38
39    Callable mGetter;
40
41    MethodCallExpr(Expr target, String name, List<Expr> args) {
42        super(Iterables.concat(Arrays.asList(target), args));
43        mName = name;
44    }
45
46    @Override
47    public void updateExpr(ModelAnalyzer modelAnalyzer) {
48        resolveType(modelAnalyzer);
49        super.updateExpr(modelAnalyzer);
50    }
51
52    @Override
53    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
54        if (mGetter == null) {
55            List<ModelClass> args = new ArrayList<ModelClass>();
56            for (Expr expr : getArgs()) {
57                args.add(expr.getResolvedType());
58            }
59
60            Expr target = getTarget();
61            boolean isStatic = target instanceof StaticIdentifierExpr;
62            ModelMethod method = target.getResolvedType().getMethod(mName, args, isStatic);
63            if (method == null) {
64                String message = "cannot find method '" + mName + "' in class " +
65                        target.getResolvedType().toJavaCode();
66                IllegalArgumentException e = new IllegalArgumentException(message);
67                L.e(e, "cannot find method %s in class %s", mName,
68                        target.getResolvedType().toJavaCode());
69                throw e;
70            }
71            if (!isStatic && method.isStatic()) {
72                // found a static method on an instance. Use class instead
73                target.getParents().remove(this);
74                getChildren().remove(target);
75                StaticIdentifierExpr staticId = getModel()
76                        .staticIdentifierFor(target.getResolvedType());
77                getChildren().add(staticId);
78                staticId.getParents().add(this);
79                // make sure we update this in case we access it below
80                target = getTarget();
81            }
82            int flags = DYNAMIC;
83            if (method.isStatic()) {
84                flags |= STATIC;
85            }
86            mGetter = new Callable(Type.METHOD, method.getName(), method.getReturnType(args), flags);
87        }
88        return mGetter.resolvedType;
89    }
90
91    @Override
92    protected List<Dependency> constructDependencies() {
93        final List<Dependency> dependencies = constructDynamicChildrenDependencies();
94        for (Dependency dependency : dependencies) {
95            if (dependency.getOther() == getTarget()) {
96                dependency.setMandatory(true);
97            }
98        }
99        return dependencies;
100    }
101
102    @Override
103    protected String computeUniqueKey() {
104        return sUniqueKeyJoiner.join(getTarget().computeUniqueKey(), mName,
105                super.computeUniqueKey());
106    }
107
108    public Expr getTarget() {
109        return getChildren().get(0);
110    }
111
112    public String getName() {
113        return mName;
114    }
115
116    public List<Expr> getArgs() {
117        return getChildren().subList(1, getChildren().size());
118    }
119
120    public Callable getGetter() {
121        return mGetter;
122    }
123}
124