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

org.jetbrains.kotlin.js.translate.utils.BindingUtils Maven / Gradle / Ivy

There is a newer version: 2.0.0-RC2
Show newest version
/*
 * Copyright 2010-2015 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.utils;

import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;

import java.util.List;

import static org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils.message;
import static org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET;
import static org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET;

/**
 * This class contains some code related to BindingContext use. Intention is not to pollute other classes.
 * Every call to BindingContext.get() is supposed to be wrapped by this utility class.
 */
public final class BindingUtils {

    private BindingUtils() {
    }

    @NotNull
    static private 
    D getDescriptorForExpression(@NotNull BindingContext context, @NotNull E expression, Class descriptorClass) {
        DeclarationDescriptor descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression);
        assert descriptor != null;
        assert descriptorClass.isInstance(descriptor)
                : message(expression, expression.toString() + " expected to have of type" + descriptorClass.toString());
        //noinspection unchecked
        return (D) descriptor;
    }

    @NotNull
    public static ClassDescriptor getClassDescriptor(@NotNull BindingContext context,
            @NotNull KtClassOrObject declaration) {
        return BindingContextUtils.getNotNull(context, BindingContext.CLASS, declaration);
    }

    @NotNull
    public static FunctionDescriptor getFunctionDescriptor(@NotNull BindingContext context,
            @NotNull KtDeclarationWithBody declaration) {
        return getDescriptorForExpression(context, declaration, FunctionDescriptor.class);
    }

    @NotNull
    public static PropertyDescriptor getPropertyDescriptor(@NotNull BindingContext context,
            @NotNull KtProperty declaration) {
        return getDescriptorForExpression(context, declaration, PropertyDescriptor.class);
    }

    @NotNull
    private static KtParameter getParameterForDescriptor(@NotNull ValueParameterDescriptor descriptor) {
        PsiElement result = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
        assert result instanceof KtParameter : message(descriptor, "ValueParameterDescriptor should have corresponding JetParameter");
        return (KtParameter) result;
    }

    public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull KtClassOrObject classDeclaration) {
        ClassDescriptor classDescriptor = getClassDescriptor(context, classDeclaration);
        List superclassDescriptors = DescriptorUtils.getSuperclassDescriptors(classDescriptor);
        return (JsDescriptorUtils.findAncestorClass(superclassDescriptors) != null);
    }

    @NotNull
    public static KotlinType getTypeByReference(@NotNull BindingContext context,
            @NotNull KtTypeReference typeReference) {
        return BindingContextUtils.getNotNull(context, BindingContext.TYPE, typeReference);
    }

    @NotNull
    public static ClassDescriptor getClassDescriptorForTypeReference(@NotNull BindingContext context,
            @NotNull KtTypeReference typeReference) {
        return DescriptorUtils.getClassDescriptorForType(getTypeByReference(context, typeReference));
    }

    @Nullable
    public static PropertyDescriptor getPropertyDescriptorForConstructorParameter(@NotNull BindingContext context,
            @NotNull KtParameter parameter) {
        return context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
    }

    @Nullable
    public static DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context,
            @NotNull KtReferenceExpression reference) {
        if (BindingContextUtils.isExpressionWithValidReference(reference, context)) {
            return BindingContextUtils.getNotNull(context, BindingContext.REFERENCE_TARGET, reference);
        }
        return null;
    }

    @Nullable
    public static DeclarationDescriptor getNullableDescriptorForReferenceExpression(@NotNull BindingContext context,
            @NotNull KtReferenceExpression reference) {
        return context.get(BindingContext.REFERENCE_TARGET, reference);
    }

    public static boolean isVariableReassignment(@NotNull BindingContext context, @NotNull KtExpression expression) {
        return BindingContextUtils.getNotNull(context, BindingContext.VARIABLE_REASSIGNMENT, expression);
    }

    @Nullable
    public static CallableDescriptor getCallableDescriptorForOperationExpression(
            @NotNull BindingContext context,
            @NotNull KtOperationExpression expression
    ) {
        KtSimpleNameExpression operationReference = expression.getOperationReference();
        DeclarationDescriptor descriptorForReferenceExpression =
                getNullableDescriptorForReferenceExpression(context, operationReference);

        if (descriptorForReferenceExpression == null) return null;

        assert descriptorForReferenceExpression instanceof CallableDescriptor :
                message(operationReference, "Operation should resolve to callable descriptor");
        return (CallableDescriptor) descriptorForReferenceExpression;
    }

    @NotNull
    public static DeclarationDescriptor getDescriptorForElement(@NotNull BindingContext context,
            @NotNull PsiElement element) {
        return BindingContextUtils.getNotNull(context, BindingContext.DECLARATION_TO_DESCRIPTOR, element);
    }

    @Nullable
    public static Object getCompileTimeValue(@NotNull BindingContext context, @NotNull KtExpression expression) {
        CompileTimeConstant compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, context);
        if (compileTimeValue != null) {
            return getCompileTimeValue(context, expression, compileTimeValue);
        }
        return null;
    }

    @Nullable
    public static Object getCompileTimeValue(@NotNull BindingContext context, @NotNull KtExpression expression, @NotNull CompileTimeConstant constant) {
        KotlinType expectedType = context.getType(expression);
        return constant.getValue(expectedType == null ? TypeUtils.NO_EXPECTED_TYPE : expectedType);
    }

    @NotNull
    public static KtExpression getDefaultArgument(@NotNull ValueParameterDescriptor parameterDescriptor) {
        ValueParameterDescriptor descriptorWhichDeclaresDefaultValue =
                getOriginalDescriptorWhichDeclaresDefaultValue(parameterDescriptor);
        KtParameter psiParameter = getParameterForDescriptor(descriptorWhichDeclaresDefaultValue);
        KtExpression defaultValue = psiParameter.getDefaultValue();
        assert defaultValue != null : message(parameterDescriptor, "No default value found in PSI");
        return defaultValue;
    }

    private static ValueParameterDescriptor getOriginalDescriptorWhichDeclaresDefaultValue(
            @NotNull ValueParameterDescriptor parameterDescriptor
    ) {
        ValueParameterDescriptor result = parameterDescriptor;
        assert DescriptorUtilsKt.hasDefaultValue(result) : message(parameterDescriptor, "Unsupplied parameter must have default value");
        // TODO: this seems incorrect, as the default value may come from _not the first_ overridden parameter
        while (!result.declaresDefaultValue()) {
            result = result.getOverriddenDescriptors().iterator().next();
        }
        return result;
    }

    @NotNull
    public static ResolvedCall getIteratorFunction(@NotNull BindingContext context,
            @NotNull KtExpression rangeExpression) {
        return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, rangeExpression);
    }

    @NotNull
    public static ResolvedCall getNextFunction(@NotNull BindingContext context,
            @NotNull KtExpression rangeExpression) {
        return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, rangeExpression);
    }

    @NotNull
    public static ResolvedCall getHasNextCallable(@NotNull BindingContext context,
            @NotNull KtExpression rangeExpression) {
        return BindingContextUtils.getNotNull(context, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, rangeExpression);
    }

    @NotNull
    public static KotlinType getTypeForExpression(@NotNull BindingContext context,
            @NotNull KtExpression expression) {
        return BindingContextUtils.getTypeNotNull(context, expression);
    }

    @NotNull
    public static ResolvedCall getResolvedCallForArrayAccess(@NotNull BindingContext context,
            @NotNull KtArrayAccessExpression arrayAccessExpression,
            boolean isGet) {
        return BindingContextUtils.getNotNull(context, isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy