android.databinding.tool.expr.LambdaExpr Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of compiler Show documentation
Show all versions of compiler Show documentation
The annotation processor for Data Binding. Generates binding classes for runtime.
The newest version!
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.databinding.tool.expr;
import android.databinding.tool.CallbackWrapper;
import android.databinding.tool.reflection.ModelAnalyzer;
import android.databinding.tool.reflection.ModelClass;
import android.databinding.tool.reflection.ModelMethod;
import android.databinding.tool.solver.ExecutionPath;
import android.databinding.tool.util.Preconditions;
import android.databinding.tool.writer.KCode;
import android.databinding.tool.writer.LayoutBinderWriterKt;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class LambdaExpr extends Expr {
private static AtomicInteger sIdCounter = new AtomicInteger();
private final int mId = sIdCounter.incrementAndGet();
private CallbackWrapper mCallbackWrapper;
// set when Binding resolves the receiver
private final CallbackExprModel mCallbackExprModel;
private int mCallbackId;
private ExecutionPath mExecutionPath;
public LambdaExpr(Expr expr, CallbackExprModel callbackExprModel) {
super(expr);
mCallbackExprModel = callbackExprModel;
}
public Expr getExpr() {
return getChildren().get(0);
}
public CallbackExprModel getCallbackExprModel() {
return mCallbackExprModel;
}
@Override
protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
Preconditions.checkNotNull(mCallbackWrapper, "Lambda expression must be resolved to its"
+ " setter first to get the type.");
return mCallbackWrapper.klass;
}
@Override
protected List constructDependencies() {
return Collections.emptyList();
}
public CallbackWrapper getCallbackWrapper() {
return mCallbackWrapper;
}
@Override
public Expr resolveListeners(ModelClass valueType, Expr parent) {
return this;
}
@Override
protected String computeUniqueKey() {
return "callback" + mId;
}
@Override
public boolean isDynamic() {
return false;
}
@Override
public void injectSafeUnboxing(ModelAnalyzer modelAnalyzer, ExprModel model) {
// nothing to do here
}
@Override
protected KCode generateCode() {
Preconditions
.checkNotNull(mCallbackWrapper, "Cannot find the callback method for %s", this);
KCode code = new KCode("");
final int minApi = mCallbackWrapper.getMinApi();
final String fieldName = LayoutBinderWriterKt.getFieldName(this);
if (minApi > 1) {
code.app("(getBuildSdkInt() < " + minApi + " ? null : ").app(fieldName).app(")");
} else {
code.app(fieldName);
}
return code;
}
@Override
public Expr cloneToModel(ExprModel model) {
return model.lambdaExpr(getExpr().cloneToModel(model), (CallbackExprModel) model);
}
public String generateConstructor() {
return getCallbackWrapper().constructForIdentifier(mCallbackId);
}
@Override
public void markAsUsed() {
super.markAsUsed();
}
@Override
protected String getInvertibleError() {
return "Lambda expressions cannot be inverted";
}
@Override
public List toExecutionPath(List paths) {
// i'm not involved.
throw new UnsupportedOperationException("should not call toExecutionPath on a lambda"
+ " expression");
}
public final ExecutionPath getExecutionPath() {
return mExecutionPath;
}
public int getCallbackId() {
return mCallbackId;
}
public void setup(ModelClass klass, ModelMethod method, int callbackId) {
mCallbackId = callbackId;
mCallbackWrapper = getModel().callbackWrapper(klass, method);
// now register the arguments as variables.
final ModelClass[] parameterTypes = method.getParameterTypes();
final List args = mCallbackExprModel.getArguments();
if (parameterTypes.length == args.size()) {
for (int i = 0; i < parameterTypes.length; i++) {
args.get(i).setClassFromCallback(parameterTypes[i]);
}
}
// first convert to execution path because we may add additional expressions
mExecutionPath = ExecutionPath.createRoot();
getExpr().toExecutionPath(mExecutionPath);
mCallbackExprModel.seal();
}
@Override
public String toString() {
String parameters = mCallbackExprModel.getArguments().stream()
.map(arg -> arg.getName())
.collect(Collectors.joining(", "));
return '(' + parameters + ") -> " + getExpr();
}
}