All Downloads are FREE. Search and download functionalities are using the official Maven repository.

android.databinding.tool.expr.LambdaExpr Maven / Gradle / Ivy

Go to download

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();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy