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.Call;
025 import org.jetbrains.jet.lang.psi.CallKey;
026 import org.jetbrains.jet.lang.psi.JetExpression;
027 import org.jetbrains.jet.lang.resolve.BindingContext;
028 import org.jetbrains.jet.lang.resolve.TraceUtil;
029 import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
030 import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext;
031 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
032 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil;
033 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
034 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
035 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
036 import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate;
037 import org.jetbrains.jet.lang.types.*;
038 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
039
040 import java.util.Collections;
041 import java.util.List;
042 import java.util.Map;
043
044 public class CallResolverUtil {
045
046 public static final JetType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
047 public static final JetType CANT_INFER_TYPE_PARAMETER = ErrorUtils.createErrorTypeWithCustomDebugName("CANT_INFER_TYPE_PARAMETER");
048 public static final JetType PLACEHOLDER_FUNCTION_TYPE = ErrorUtils.createErrorTypeWithCustomDebugName("PLACEHOLDER_FUNCTION_TYPE");
049
050 public static enum ResolveArgumentsMode {
051 RESOLVE_FUNCTION_ARGUMENTS,
052 SKIP_FUNCTION_ARGUMENTS
053 }
054
055 private CallResolverUtil() {}
056
057 public static <D extends CallableDescriptor> ResolvedCallImpl<D> copy(@NotNull ResolvedCallImpl<D> call, @NotNull CallResolutionContext<?> context) {
058 ResolutionCandidate<D> candidate = ResolutionCandidate.create(call.getCandidateDescriptor(), call.getThisObject(),
059 call.getReceiverArgument(), call.getExplicitReceiverKind(),
060 call.isSafeCall());
061
062 ResolvedCallImpl<D> copy = ResolvedCallImpl.create(candidate, TraceUtil.DELEGATING_TRACE_STUB, call.getTracing(), call.getDataFlowInfoForArguments());
063 context.trace.record(BindingContext.RESOLVED_CALL, context.call.getCalleeExpression(), copy);
064
065 copy.addStatus(call.getStatus());
066 if (call.isDirty()) {
067 copy.argumentHasNoType();
068 }
069 copy.setHasUnknownTypeParameters(call.hasIncompleteTypeParameters());
070 ConstraintSystem constraintSystem = call.getConstraintSystem();
071 if (constraintSystem != null) {
072 copy.setConstraintSystem(constraintSystem.copy());
073 }
074 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : call.getValueArguments().entrySet()) {
075 copy.recordValueArgument(entry.getKey(), entry.getValue());
076 }
077 return copy;
078 }
079
080
081 public static boolean hasUnknownFunctionParameter(@NotNull JetType type) {
082 assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
083 List<TypeProjection> arguments = type.getArguments();
084 // last argument is return type of function type
085 List<TypeProjection> functionParameters = arguments.subList(0, arguments.size() - 1);
086 for (TypeProjection functionParameter : functionParameters) {
087 if (TypeUtils.equalsOrContainsAsArgument(functionParameter.getType(), CANT_INFER_TYPE_PARAMETER, DONT_CARE)) {
088 return true;
089 }
090 }
091 return false;
092 }
093
094 public static boolean hasUnknownReturnType(@NotNull JetType type) {
095 assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
096 JetType returnTypeFromFunctionType = KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(type);
097 return ErrorUtils.containsErrorType(returnTypeFromFunctionType);
098 }
099
100 public static JetType replaceReturnTypeByUnknown(@NotNull JetType type) {
101 assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type);
102 List<TypeProjection> arguments = type.getArguments();
103 List<TypeProjection> newArguments = Lists.newArrayList();
104 newArguments.addAll(arguments.subList(0, arguments.size() - 1));
105 newArguments.add(new TypeProjection(Variance.INVARIANT, DONT_CARE));
106 return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
107 }
108
109 private static boolean hasReturnTypeDependentOnNotInferredParams(@NotNull ResolvedCallImpl<?> callToComplete) {
110 ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
111 if (constraintSystem == null) return false;
112
113 CallableDescriptor candidateDescriptor = callToComplete.getCandidateDescriptor();
114 JetType returnType = candidateDescriptor.getReturnType();
115 if (returnType == null) return false;
116
117 for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
118 JetType inferredValueForTypeVariable = ConstraintsUtil.getValue(constraintSystem.getTypeConstraints(typeVariable));
119 if (inferredValueForTypeVariable == null) {
120 if (TypeUtils.dependsOnTypeParameters(returnType, Collections.singleton(typeVariable))) {
121 return true;
122 }
123 }
124 }
125 return false;
126 }
127
128 public static boolean hasInferredReturnType(ResolvedCallWithTrace<?> call) {
129 ResolvedCallImpl<?> callToComplete = call.getCallToCompleteTypeArgumentInference();
130 if (hasReturnTypeDependentOnNotInferredParams(callToComplete)) return false;
131
132 // Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
133 ConstraintSystem constraintSystem = callToComplete.getConstraintSystem();
134 if (constraintSystem != null && constraintSystem.hasOnlyExpectedTypeMismatch()) return false;
135 return true;
136 }
137
138 @Nullable
139 public static CallKey createCallKey(@NotNull BasicCallResolutionContext context) {
140 if (context.call.getCallType() == Call.CallType.INVOKE) {
141 return null;
142 }
143 PsiElement callElement = context.call.getCallElement();
144 if (!(callElement instanceof JetExpression)) return null;
145 return CallKey.create(context.call.getCallType(), (JetExpression) callElement);
146 }
147
148 @NotNull
149 public static JetType getErasedReceiverType(
150 @NotNull ReceiverParameterDescriptor receiverParameterDescriptor,
151 @NotNull CallableDescriptor descriptor
152 ) {
153 JetType receiverType = receiverParameterDescriptor.getType();
154 for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
155 if (typeParameter.getTypeConstructor().equals(receiverType.getConstructor())) {
156 receiverType = typeParameter.getUpperBoundsAsType();
157 }
158 }
159 List<TypeProjection> fakeTypeArguments = Lists.newArrayList();
160 for (TypeProjection typeProjection : receiverType.getArguments()) {
161 fakeTypeArguments.add(new TypeProjection(typeProjection.getProjectionKind(), DONT_CARE));
162 }
163 return new JetTypeImpl(
164 receiverType.getAnnotations(), receiverType.getConstructor(), receiverType.isNullable(),
165 fakeTypeArguments, ErrorUtils.createErrorScope("Error scope for erased receiver type", /*throwExceptions=*/true));
166 }
167
168 public static boolean isOrOverridesSynthesized(@NotNull CallableMemberDescriptor descriptor) {
169 if (descriptor.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
170 return true;
171 }
172 if (descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
173 for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
174 if (!isOrOverridesSynthesized(overridden)) {
175 return false;
176 }
177 }
178 return true;
179 }
180 return false;
181 }
182 }