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