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 org.jetbrains.annotations.NotNull; 021import org.jetbrains.annotations.Nullable; 022import org.jetbrains.jet.lang.descriptors.CallableDescriptor; 023import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; 024import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 025import org.jetbrains.jet.lang.diagnostics.Errors; 026import org.jetbrains.jet.lang.psi.*; 027import org.jetbrains.jet.lang.resolve.BindingTrace; 028import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; 029import org.jetbrains.jet.lang.resolve.TypeResolver; 030import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext; 031import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode; 032import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode; 033import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl; 034import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; 035import org.jetbrains.jet.lang.resolve.scopes.JetScope; 036import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; 037import org.jetbrains.jet.lang.types.ErrorUtils; 038import org.jetbrains.jet.lang.types.JetType; 039import org.jetbrains.jet.lang.types.JetTypeInfo; 040import org.jetbrains.jet.lang.types.TypeUtils; 041import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 042import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; 043import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 044 045import javax.inject.Inject; 046import java.util.Collections; 047import java.util.List; 048import java.util.Map; 049import java.util.Set; 050 051import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getRecordedTypeInfo; 052import static org.jetbrains.jet.lang.resolve.BindingContextUtils.recordExpressionType; 053import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.*; 054import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS; 055import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SKIP_FUNCTION_ARGUMENTS; 056import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; 057 058public class ArgumentTypeResolver { 059 060 @NotNull 061 private TypeResolver typeResolver; 062 @NotNull 063 private ExpressionTypingServices expressionTypingServices; 064 065 @Inject 066 public void setTypeResolver(@NotNull TypeResolver typeResolver) { 067 this.typeResolver = typeResolver; 068 } 069 070 @Inject 071 public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) { 072 this.expressionTypingServices = expressionTypingServices; 073 } 074 075 public static boolean isSubtypeOfForArgumentType(@NotNull JetType subtype, @NotNull JetType supertype) { 076 if (subtype == PLACEHOLDER_FUNCTION_TYPE) { 077 return isFunctionOrErrorType(supertype) || KotlinBuiltIns.getInstance().isAny(supertype); //todo function type extends 078 } 079 if (supertype == PLACEHOLDER_FUNCTION_TYPE) { 080 return isFunctionOrErrorType(subtype); //todo extends function type 081 } 082 return JetTypeChecker.INSTANCE.isSubtypeOf(subtype, supertype); 083 } 084 085 private static boolean isFunctionOrErrorType(@NotNull JetType supertype) { 086 return KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(supertype) || ErrorUtils.isErrorType(supertype); 087 } 088 089 public void checkTypesWithNoCallee(@NotNull CallResolutionContext<?> context) { 090 checkTypesWithNoCallee(context, SKIP_FUNCTION_ARGUMENTS); 091 } 092 093 public void checkTypesWithNoCallee(@NotNull CallResolutionContext<?> context, @NotNull ResolveArgumentsMode resolveFunctionArgumentBodies) { 094 if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return; 095 096 for (ValueArgument valueArgument : context.call.getValueArguments()) { 097 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 098 if (argumentExpression != null && !(argumentExpression instanceof JetFunctionLiteralExpression)) { 099 expressionTypingServices.getType(context.scope, argumentExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); 100 } 101 } 102 103 if (resolveFunctionArgumentBodies == RESOLVE_FUNCTION_ARGUMENTS) { 104 checkTypesForFunctionArgumentsWithNoCallee(context); 105 } 106 107 for (JetTypeProjection typeProjection : context.call.getTypeArguments()) { 108 JetTypeReference typeReference = typeProjection.getTypeReference(); 109 if (typeReference == null) { 110 context.trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection)); 111 } 112 else { 113 typeResolver.resolveType(context.scope, typeReference, context.trace, true); 114 } 115 } 116 } 117 118 public void checkTypesForFunctionArgumentsWithNoCallee(@NotNull CallResolutionContext<?> context) { 119 if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return; 120 121 for (ValueArgument valueArgument : context.call.getValueArguments()) { 122 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 123 if (argumentExpression != null && (argumentExpression instanceof JetFunctionLiteralExpression)) { 124 expressionTypingServices.getType(context.scope, argumentExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); 125 } 126 } 127 128 for (JetExpression expression : context.call.getFunctionLiteralArguments()) { 129 expressionTypingServices.getType(context.scope, expression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); 130 } 131 } 132 133 public void checkUnmappedArgumentTypes(CallResolutionContext<?> context, Set<ValueArgument> unmappedArguments) { 134 for (ValueArgument valueArgument : unmappedArguments) { 135 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 136 if (argumentExpression != null) { 137 expressionTypingServices.getType(context.scope, argumentExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); 138 } 139 } 140 } 141 142 public <D extends CallableDescriptor> void checkTypesForFunctionArguments(CallResolutionContext<?> context, ResolvedCallImpl<D> resolvedCall) { 143 Map<ValueParameterDescriptor, ResolvedValueArgument> arguments = resolvedCall.getValueArguments(); 144 for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : arguments.entrySet()) { 145 ValueParameterDescriptor valueParameterDescriptor = entry.getKey(); 146 JetType varargElementType = valueParameterDescriptor.getVarargElementType(); 147 JetType functionType; 148 if (varargElementType != null) { 149 functionType = varargElementType; 150 } 151 else { 152 functionType = valueParameterDescriptor.getType(); 153 } 154 ResolvedValueArgument valueArgument = entry.getValue(); 155 List<ValueArgument> valueArguments = valueArgument.getArguments(); 156 for (ValueArgument argument : valueArguments) { 157 JetExpression expression = argument.getArgumentExpression(); 158 if (expression instanceof JetFunctionLiteralExpression) { 159 expressionTypingServices.getType(context.scope, expression, functionType, context.dataFlowInfo, context.trace); 160 } 161 } 162 } 163 } 164 165 @NotNull 166 public JetTypeInfo getArgumentTypeInfo( 167 @Nullable JetExpression expression, 168 @NotNull CallResolutionContext<?> context, 169 @NotNull ResolveArgumentsMode resolveArgumentsMode, 170 @Nullable TemporaryBindingTrace traceToCommitForCall 171 ) { 172 if (expression == null) { 173 return JetTypeInfo.create(null, context.dataFlowInfo); 174 } 175 if (expression instanceof JetFunctionLiteralExpression) { 176 return getFunctionLiteralTypeInfo((JetFunctionLiteralExpression) expression, context, resolveArgumentsMode); 177 } 178 JetTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext()); 179 if (recordedTypeInfo != null) { 180 return recordedTypeInfo; 181 } 182 //todo deparenthesize 183 CallExpressionResolver callExpressionResolver = expressionTypingServices.getCallExpressionResolver(); 184 if (!(expression instanceof JetCallExpression) && !(expression instanceof JetQualifiedExpression)) { 185 return expressionTypingServices.getTypeInfo(context.scope, expression, context.expectedType, context.dataFlowInfo, context.trace); 186 } 187 188 JetTypeInfo result; 189 if (expression instanceof JetCallExpression) { 190 result = callExpressionResolver.getCallExpressionTypeInfo( 191 (JetCallExpression) expression, ReceiverValue.NO_RECEIVER, null, 192 context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE), ResolveMode.NESTED_CALL, context.resolutionResultsCache); 193 } 194 else { // expression instanceof JetQualifiedExpression 195 result = callExpressionResolver.getQualifiedExpressionTypeInfo( 196 (JetQualifiedExpression) expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE), 197 ResolveMode.NESTED_CALL, context.resolutionResultsCache); 198 } 199 200 recordExpressionType(expression, context.trace, context.scope, result); 201 if (traceToCommitForCall != null) { 202 traceToCommitForCall.commit(); 203 } 204 return result; 205 } 206 207 @NotNull 208 public JetTypeInfo getFunctionLiteralTypeInfo( 209 @NotNull JetFunctionLiteralExpression functionLiteralExpression, 210 @NotNull CallResolutionContext<?> context, 211 @NotNull ResolveArgumentsMode resolveArgumentsMode 212 ) { 213 if (resolveArgumentsMode == SKIP_FUNCTION_ARGUMENTS) { 214 JetType type = getFunctionLiteralType(functionLiteralExpression, context.scope, context.trace); 215 return JetTypeInfo.create(type, context.dataFlowInfo); 216 } 217 return expressionTypingServices.getTypeInfo(context.scope, functionLiteralExpression, context.expectedType, context.dataFlowInfo, context.trace); 218 } 219 220 @Nullable 221 private JetType getFunctionLiteralType( 222 @NotNull JetFunctionLiteralExpression expression, 223 @NotNull JetScope scope, 224 @NotNull BindingTrace trace 225 ) { 226 List<JetParameter> valueParameters = expression.getValueParameters(); 227 if (valueParameters.isEmpty()) { 228 return PLACEHOLDER_FUNCTION_TYPE; 229 } 230 TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create( 231 trace, "trace to resolve function literal parameter types"); 232 List<JetType> parameterTypes = Lists.newArrayList(); 233 for (JetParameter parameter : valueParameters) { 234 parameterTypes.add(resolveTypeRefWithDefault(parameter.getTypeReference(), scope, temporaryTrace, DONT_CARE)); 235 } 236 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); 237 JetType returnType = resolveTypeRefWithDefault(functionLiteral.getReturnTypeRef(), scope, temporaryTrace, DONT_CARE); 238 assert returnType != null; 239 JetType receiverType = resolveTypeRefWithDefault(functionLiteral.getReceiverTypeRef(), scope, temporaryTrace, null); 240 return KotlinBuiltIns.getInstance().getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiverType, parameterTypes, returnType); 241 } 242 243 @Nullable 244 public JetType resolveTypeRefWithDefault( 245 @Nullable JetTypeReference returnTypeRef, 246 @NotNull JetScope scope, 247 @NotNull BindingTrace trace, 248 @Nullable JetType defaultValue 249 ) { 250 if (returnTypeRef != null) { 251 return expressionTypingServices.getTypeResolver().resolveType(scope, returnTypeRef, trace, true); 252 } 253 return defaultValue; 254 } 255}