001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.resolve.calls;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.psi.PsiElement;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.jet.lang.descriptors.*;
024    import org.jetbrains.jet.lang.psi.*;
025    import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
026    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
027    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
028    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
029    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
030    import org.jetbrains.jet.lang.types.*;
031    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
032    
033    import java.util.Collections;
034    import java.util.List;
035    
036    import static org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE;
037    
038    public class CallResolverUtil {
039        public static enum ResolveArgumentsMode {
040            RESOLVE_FUNCTION_ARGUMENTS,
041            SHAPE_FUNCTION_ARGUMENTS
042        }
043    
044        private CallResolverUtil() {}
045    
046    
047        public static boolean hasUnknownFunctionParameter(@NotNull JetType type) {
048            assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
049            List<TypeProjection> arguments = type.getArguments();
050            // last argument is return type of function type
051            List<TypeProjection> functionParameters = arguments.subList(0, arguments.size() - 1);
052            for (TypeProjection functionParameter : functionParameters) {
053                if (TypeUtils.containsSpecialType(functionParameter.getType(), DONT_CARE)
054                    || ErrorUtils.containsUninferredParameter(functionParameter.getType())) {
055                    return true;
056                }
057            }
058            return false;
059        }
060    
061        public static boolean hasUnknownReturnType(@NotNull JetType type) {
062            assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
063            JetType returnTypeFromFunctionType = KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(type);
064            return ErrorUtils.containsErrorType(returnTypeFromFunctionType);
065        }
066    
067        public static JetType replaceReturnTypeByUnknown(@NotNull JetType type) {
068            assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
069            List<TypeProjection> arguments = type.getArguments();
070            List<TypeProjection> newArguments = Lists.newArrayList();
071            newArguments.addAll(arguments.subList(0, arguments.size() - 1));
072            newArguments.add(new TypeProjectionImpl(Variance.INVARIANT, DONT_CARE));
073            return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
074        }
075    
076        private static boolean hasReturnTypeDependentOnUninferredParams(
077                @NotNull CallableDescriptor candidateDescriptor,
078                @NotNull ConstraintSystem constraintSystem
079        ) {
080            JetType returnType = candidateDescriptor.getReturnType();
081            if (returnType == null) return false;
082    
083            for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
084                JetType inferredValueForTypeVariable = constraintSystem.getTypeBounds(typeVariable).getValue();
085                if (inferredValueForTypeVariable == null) {
086                    if (TypeUtils.dependsOnTypeParameters(returnType, Collections.singleton(typeVariable))) {
087                        return true;
088                    }
089                }
090            }
091            return false;
092        }
093    
094        public static boolean hasInferredReturnType(
095                @NotNull CallableDescriptor candidateDescriptor,
096                @NotNull ConstraintSystem constraintSystem
097        ) {
098            if (hasReturnTypeDependentOnUninferredParams(candidateDescriptor, constraintSystem)) return false;
099    
100            // Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
101            if (constraintSystem.getStatus().hasOnlyErrorsFromPosition(ConstraintPosition.EXPECTED_TYPE_POSITION)) return false;
102            return true;
103        }
104    
105        @NotNull
106        public static JetType getErasedReceiverType(
107                @NotNull ReceiverParameterDescriptor receiverParameterDescriptor,
108                @NotNull CallableDescriptor descriptor
109        ) {
110            JetType receiverType = receiverParameterDescriptor.getType();
111            for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
112                if (typeParameter.getTypeConstructor().equals(receiverType.getConstructor())) {
113                    receiverType = typeParameter.getUpperBoundsAsType();
114                }
115            }
116            List<TypeProjection> fakeTypeArguments = Lists.newArrayList();
117            for (TypeProjection typeProjection : receiverType.getArguments()) {
118                fakeTypeArguments.add(new TypeProjectionImpl(typeProjection.getProjectionKind(), DONT_CARE));
119            }
120            return new JetTypeImpl(
121                    receiverType.getAnnotations(), receiverType.getConstructor(), receiverType.isNullable(),
122                    fakeTypeArguments, ErrorUtils.createErrorScope("Error scope for erased receiver type", /*throwExceptions=*/true));
123        }
124    
125        public static boolean isOrOverridesSynthesized(@NotNull CallableMemberDescriptor descriptor) {
126            if (descriptor.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
127                return true;
128            }
129            if (descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
130                for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
131                    if (!isOrOverridesSynthesized(overridden)) {
132                        return false;
133                    }
134                }
135                return true;
136            }
137            return false;
138        }
139    
140        public static boolean isInvokeCallOnVariable(@NotNull Call call) {
141            if (call.getCallType() != Call.CallType.INVOKE) return false;
142            ReceiverValue thisObject = call.getThisObject();
143            //calleeExpressionAsThisObject for invoke is always ExpressionReceiver, see CallForImplicitInvoke
144            JetExpression expression = ((ExpressionReceiver) thisObject).getExpression();
145            return expression instanceof JetSimpleNameExpression;
146        }
147    
148        public static boolean isInvokeCallOnExpressionWithBothReceivers(@NotNull Call call) {
149            if (call.getCallType() != Call.CallType.INVOKE || isInvokeCallOnVariable(call)) return false;
150            return call.getExplicitReceiver().exists() && call.getThisObject().exists();
151        }
152    }