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

org.jetbrains.jet.lang.resolve.calls.CallResolverUtil Maven / Gradle / Ivy

/*
 * Copyright 2010-2013 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.jet.lang.resolve.calls;

import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;

import java.util.Collections;
import java.util.List;

import static org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE;

public class CallResolverUtil {
    public static enum ResolveArgumentsMode {
        RESOLVE_FUNCTION_ARGUMENTS,
        SHAPE_FUNCTION_ARGUMENTS
    }

    private CallResolverUtil() {}


    public static boolean hasUnknownFunctionParameter(@NotNull JetType type) {
        assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
        List arguments = type.getArguments();
        // last argument is return type of function type
        List functionParameters = arguments.subList(0, arguments.size() - 1);
        for (TypeProjection functionParameter : functionParameters) {
            if (TypeUtils.containsSpecialType(functionParameter.getType(), DONT_CARE)
                || ErrorUtils.containsUninferredParameter(functionParameter.getType())) {
                return true;
            }
        }
        return false;
    }

    public static boolean hasUnknownReturnType(@NotNull JetType type) {
        assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
        JetType returnTypeFromFunctionType = KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(type);
        return ErrorUtils.containsErrorType(returnTypeFromFunctionType);
    }

    public static JetType replaceReturnTypeByUnknown(@NotNull JetType type) {
        assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
        List arguments = type.getArguments();
        List newArguments = Lists.newArrayList();
        newArguments.addAll(arguments.subList(0, arguments.size() - 1));
        newArguments.add(new TypeProjectionImpl(Variance.INVARIANT, DONT_CARE));
        return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
    }

    private static boolean hasReturnTypeDependentOnUninferredParams(
            @NotNull CallableDescriptor candidateDescriptor,
            @NotNull ConstraintSystem constraintSystem
    ) {
        JetType returnType = candidateDescriptor.getReturnType();
        if (returnType == null) return false;

        for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
            JetType inferredValueForTypeVariable = constraintSystem.getTypeBounds(typeVariable).getValue();
            if (inferredValueForTypeVariable == null) {
                if (TypeUtils.dependsOnTypeParameters(returnType, Collections.singleton(typeVariable))) {
                    return true;
                }
            }
        }
        return false;
    }

    public static boolean hasInferredReturnType(
            @NotNull CallableDescriptor candidateDescriptor,
            @NotNull ConstraintSystem constraintSystem
    ) {
        if (hasReturnTypeDependentOnUninferredParams(candidateDescriptor, constraintSystem)) return false;

        // Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
        if (constraintSystem.getStatus().hasOnlyErrorsFromPosition(ConstraintPosition.EXPECTED_TYPE_POSITION)) return false;
        return true;
    }

    @Nullable
    public static CallKey createCallKey(@NotNull BasicCallResolutionContext context) {
        if (isInvokeCallOnVariable(context.call)) {
            return null;
        }
        PsiElement callElement = context.call.getCallElement();
        if (!(callElement instanceof JetExpression)) return null;
        return CallKey.create(context.call.getCallType(), (JetExpression) callElement);
    }

    @NotNull
    public static JetType getErasedReceiverType(
            @NotNull ReceiverParameterDescriptor receiverParameterDescriptor,
            @NotNull CallableDescriptor descriptor
    ) {
        JetType receiverType = receiverParameterDescriptor.getType();
        for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
            if (typeParameter.getTypeConstructor().equals(receiverType.getConstructor())) {
                receiverType = typeParameter.getUpperBoundsAsType();
            }
        }
        List fakeTypeArguments = Lists.newArrayList();
        for (TypeProjection typeProjection : receiverType.getArguments()) {
            fakeTypeArguments.add(new TypeProjectionImpl(typeProjection.getProjectionKind(), DONT_CARE));
        }
        return new JetTypeImpl(
                receiverType.getAnnotations(), receiverType.getConstructor(), receiverType.isNullable(),
                fakeTypeArguments, ErrorUtils.createErrorScope("Error scope for erased receiver type", /*throwExceptions=*/true));
    }

    public static boolean isOrOverridesSynthesized(@NotNull CallableMemberDescriptor descriptor) {
        if (descriptor.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
            return true;
        }
        if (descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
            for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
                if (!isOrOverridesSynthesized(overridden)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    public static boolean isInvokeCallOnVariable(@NotNull Call call) {
        if (call.getCallType() != Call.CallType.INVOKE) return false;
        ReceiverValue thisObject = call.getThisObject();
        //calleeExpressionAsThisObject for invoke is always ExpressionReceiver, see CallForImplicitInvoke
        JetExpression expression = ((ExpressionReceiver) thisObject).getExpression();
        return expression instanceof JetSimpleNameExpression;
    }

    public static boolean isInvokeCallOnExpressionWithBothReceivers(@NotNull Call call) {
        if (call.getCallType() != Call.CallType.INVOKE || isInvokeCallOnVariable(call)) return false;
        return call.getExplicitReceiver().exists() && call.getThisObject().exists();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy