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

org.jetbrains.kotlin.js.translate.operation.InOperationTranslator Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2016 JetBrains s.r.o.
 *
 * 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 org.jetbrains.kotlin.js.translate.operation;

import org.jetbrains.kotlin.js.backend.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.js.patterns.DescriptorPredicate;
import org.jetbrains.kotlin.js.patterns.PatternBuilder;
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.general.Translation;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;

/**
 * Translates 'A in B' expression applying specialization if possible
 */
public class InOperationTranslator extends AbstractTranslator {
    private static final DescriptorPredicate INT_SPECIALIZATION_TEST = PatternBuilder.pattern("ranges.IntRange.contains");
    private static final DescriptorPredicate INT_RANGE_TEST = PatternBuilder.pattern("Int.rangeTo");
    private final JsExpression left;
    private final KtExpression right;
    private final KtSimpleNameExpression operation;
    private final boolean negated;

    public InOperationTranslator(@NotNull TranslationContext context, @NotNull JsExpression left, @NotNull KtExpression right,
            @NotNull KtSimpleNameExpression operation, boolean negated) {
        super(context);
        this.left = left;
        this.right = right;
        this.operation = operation;
        this.negated = negated;
    }

    @NotNull
    public JsExpression translate() {
        ResolvedCall call = CallUtilKt.getFunctionResolvedCallWithAssert(operation, bindingContext());
        if (INT_SPECIALIZATION_TEST.test(call.getResultingDescriptor())) {
            JsExpression candidate = translateInt();
            if (candidate != null) {
                return candidate;
            }
        }
        JsExpression rightTranslated = Translation.translateAsExpression(right, context());
        return translateGeneral(call, rightTranslated);
    }

    @NotNull
    private JsExpression translateGeneral(@NotNull ResolvedCall call, @NotNull JsExpression rightTranslated) {
        JsExpression result = CallTranslator.translate(context(), call, rightTranslated);
        if (negated) {
            result = JsAstUtils.not(result);
        }
        return result;
    }

    @Nullable
    private JsExpression translateInt() {
        ResolvedCall rightCall = CallUtilKt.getResolvedCallWithAssert(right, bindingContext());
        if (!(rightCall.getResultingDescriptor() instanceof FunctionDescriptor)) {
            return null;
        }
        FunctionDescriptor callDescriptor = (FunctionDescriptor) rightCall.getResultingDescriptor();
        if (!INT_RANGE_TEST.test(callDescriptor)) {
            return null;
        }
        if (!(rightCall.getDispatchReceiver() instanceof ExpressionReceiver)) {
            return null;
        }

        KtExpression lower = ((ExpressionReceiver) rightCall.getDispatchReceiver()).getExpression();
        KtExpression upper = rightCall.getCall().getValueArguments().get(0).getArgumentExpression();
        assert upper != null : "Parse error occurred: " + PsiUtilsKt.getTextWithLocation(right);
        return translateInt(lower, upper);
    }

    @NotNull
    private JsExpression translateInt(@NotNull KtExpression lowerExpression, @NotNull KtExpression upperExpression) {
        JsExpression lower = Translation.translateAsExpression(lowerExpression, context());
        JsExpression upper = Translation.translateAsExpression(upperExpression, context());
        if (!negated) {
            JsExpression first = JsAstUtils.greaterThanEq(left, lower);
            JsExpression second = JsAstUtils.lessThanEq(left, upper);
            return JsAstUtils.and(first, second);
        }
        else {
            JsExpression first = JsAstUtils.lessThan(left, lower);
            JsExpression second = JsAstUtils.greaterThan(left, upper);
            return JsAstUtils.or(first, second);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy