001    /*
002     * Copyright 2010-2015 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.kotlin.resolve.calls;
018    
019    import com.google.common.collect.Lists;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
023    import org.jetbrains.kotlin.builtins.ReflectionTypes;
024    import org.jetbrains.kotlin.descriptors.CallableDescriptor;
025    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
026    import org.jetbrains.kotlin.diagnostics.Errors;
027    import org.jetbrains.kotlin.psi.*;
028    import org.jetbrains.kotlin.resolve.BindingTrace;
029    import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
030    import org.jetbrains.kotlin.resolve.TypeResolver;
031    import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesResolutionUtilsKt;
032    import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
033    import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
034    import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
035    import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
036    import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImplKt;
037    import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
038    import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
039    import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor;
040    import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
041    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
042    import org.jetbrains.kotlin.types.FunctionPlaceholders;
043    import org.jetbrains.kotlin.types.FunctionPlaceholdersKt;
044    import org.jetbrains.kotlin.types.KotlinType;
045    import org.jetbrains.kotlin.types.TypeUtils;
046    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
047    import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
048    import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
049    import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
050    
051    import java.util.Collections;
052    import java.util.List;
053    
054    import static org.jetbrains.kotlin.psi.KtPsiUtil.getLastElementDeparenthesized;
055    import static org.jetbrains.kotlin.resolve.BindingContextUtils.getRecordedTypeInfo;
056    import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
057    import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
058    import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
059    import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
060    import static org.jetbrains.kotlin.types.TypeUtils.DONT_CARE;
061    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
062    
063    public class ArgumentTypeResolver {
064        @NotNull private final TypeResolver typeResolver;
065        @NotNull private final CallResolver callResolver;
066        @NotNull private final ExpressionTypingServices expressionTypingServices;
067        @NotNull private final KotlinBuiltIns builtIns;
068        @NotNull private final ReflectionTypes reflectionTypes;
069        @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
070        @NotNull private final FunctionPlaceholders functionPlaceholders;
071    
072        public ArgumentTypeResolver(
073                @NotNull TypeResolver typeResolver,
074                @NotNull CallResolver callResolver,
075                @NotNull ExpressionTypingServices expressionTypingServices,
076                @NotNull KotlinBuiltIns builtIns,
077                @NotNull ReflectionTypes reflectionTypes,
078                @NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
079                @NotNull FunctionPlaceholders functionPlaceholders
080        ) {
081            this.typeResolver = typeResolver;
082            this.callResolver = callResolver;
083            this.expressionTypingServices = expressionTypingServices;
084            this.builtIns = builtIns;
085            this.reflectionTypes = reflectionTypes;
086            this.constantExpressionEvaluator = constantExpressionEvaluator;
087            this.functionPlaceholders = functionPlaceholders;
088        }
089    
090        public static boolean isSubtypeOfForArgumentType(
091                @NotNull KotlinType actualType,
092                @NotNull KotlinType expectedType
093        ) {
094            if (FunctionPlaceholdersKt.isFunctionPlaceholder(actualType)) {
095                KotlinType functionType = ConstraintSystemBuilderImplKt.createTypeForFunctionPlaceholder(actualType, expectedType);
096                return KotlinTypeChecker.DEFAULT.isSubtypeOf(functionType, expectedType);
097            }
098            return KotlinTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType);
099        }
100    
101        public void checkTypesWithNoCallee(@NotNull CallResolutionContext<?> context) {
102            checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
103        }
104    
105        public void checkTypesWithNoCallee(
106                @NotNull CallResolutionContext<?> context,
107                @NotNull ResolveArgumentsMode resolveFunctionArgumentBodies
108        ) {
109            if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
110    
111            for (ValueArgument valueArgument : context.call.getValueArguments()) {
112                KtExpression argumentExpression = valueArgument.getArgumentExpression();
113                if (argumentExpression != null && !(argumentExpression instanceof KtLambdaExpression)) {
114                    checkArgumentTypeWithNoCallee(context, argumentExpression);
115                }
116            }
117    
118            if (resolveFunctionArgumentBodies == RESOLVE_FUNCTION_ARGUMENTS) {
119                checkTypesForFunctionArgumentsWithNoCallee(context);
120            }
121    
122            for (KtTypeProjection typeProjection : context.call.getTypeArguments()) {
123                KtTypeReference typeReference = typeProjection.getTypeReference();
124                if (typeReference == null) {
125                    context.trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection));
126                }
127                else {
128                    typeResolver.resolveType(context.scope, typeReference, context.trace, true);
129                }
130            }
131        }
132    
133        public void checkTypesForFunctionArgumentsWithNoCallee(@NotNull CallResolutionContext<?> context) {
134            if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
135    
136            for (ValueArgument valueArgument : context.call.getValueArguments()) {
137                KtExpression argumentExpression = valueArgument.getArgumentExpression();
138                if (argumentExpression != null && isFunctionLiteralArgument(argumentExpression, context)) {
139                    checkArgumentTypeWithNoCallee(context, argumentExpression);
140                }
141            }
142        }
143    
144        private void checkArgumentTypeWithNoCallee(CallResolutionContext<?> context, KtExpression argumentExpression) {
145            expressionTypingServices.getTypeInfo(argumentExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
146            updateResultArgumentTypeIfNotDenotable(context, argumentExpression);
147        }
148    
149        public static boolean isFunctionLiteralArgument(
150                @NotNull KtExpression expression, @NotNull ResolutionContext context
151        ) {
152            return getFunctionLiteralArgumentIfAny(expression, context) != null;
153        }
154    
155        @NotNull
156        public static KtFunction getFunctionLiteralArgument(
157                @NotNull KtExpression expression, @NotNull ResolutionContext context
158        ) {
159            assert isFunctionLiteralArgument(expression, context);
160            //noinspection ConstantConditions
161            return getFunctionLiteralArgumentIfAny(expression, context);
162        }
163    
164        @Nullable
165        public static KtFunction getFunctionLiteralArgumentIfAny(
166                @NotNull KtExpression expression, @NotNull ResolutionContext context
167        ) {
168            KtExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
169            if (deparenthesizedExpression instanceof KtLambdaExpression) {
170                return ((KtLambdaExpression) deparenthesizedExpression).getFunctionLiteral();
171            }
172            if (deparenthesizedExpression instanceof KtFunction) {
173                return (KtFunction) deparenthesizedExpression;
174            }
175            return null;
176        }
177    
178        @Nullable
179        public static KtCallableReferenceExpression getCallableReferenceExpressionIfAny(
180                @NotNull KtExpression expression,
181                @NotNull CallResolutionContext<?> context
182        ) {
183            KtExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
184            if (deparenthesizedExpression instanceof KtCallableReferenceExpression) {
185                return (KtCallableReferenceExpression) deparenthesizedExpression;
186            }
187            return null;
188        }
189    
190        @NotNull
191        public KotlinTypeInfo getArgumentTypeInfo(
192                @Nullable KtExpression expression,
193                @NotNull CallResolutionContext<?> context,
194                @NotNull ResolveArgumentsMode resolveArgumentsMode
195        ) {
196            if (expression == null) {
197                return TypeInfoFactoryKt.noTypeInfo(context);
198            }
199    
200            KtFunction functionLiteralArgument = getFunctionLiteralArgumentIfAny(expression, context);
201            if (functionLiteralArgument != null) {
202                return getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, resolveArgumentsMode);
203            }
204    
205            KtCallableReferenceExpression callableReferenceExpression = getCallableReferenceExpressionIfAny(expression, context);
206            if (callableReferenceExpression != null) {
207                return getCallableReferenceTypeInfo(expression, callableReferenceExpression, context, resolveArgumentsMode);
208            }
209    
210            KotlinTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext());
211            if (recordedTypeInfo != null) {
212                return recordedTypeInfo;
213            }
214    
215            ResolutionContext newContext = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(DEPENDENT);
216    
217            return expressionTypingServices.getTypeInfo(expression, newContext);
218        }
219    
220        @NotNull
221        public KotlinTypeInfo getCallableReferenceTypeInfo(
222                @NotNull KtExpression expression,
223                @NotNull KtCallableReferenceExpression callableReferenceExpression,
224                @NotNull CallResolutionContext<?> context,
225                @NotNull ResolveArgumentsMode resolveArgumentsMode
226        ) {
227            if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
228                KotlinType type = getShapeTypeOfCallableReference(callableReferenceExpression, context, true);
229                return TypeInfoFactoryKt.createTypeInfo(type);
230            }
231            return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
232        }
233    
234        @Nullable
235        public KotlinType getShapeTypeOfCallableReference(
236                @NotNull KtCallableReferenceExpression callableReferenceExpression,
237                @NotNull CallResolutionContext<?> context,
238                boolean expectedTypeIsUnknown
239        ) {
240            KotlinType receiverType =
241                    CallableReferencesResolutionUtilsKt.resolveCallableReferenceReceiverType(callableReferenceExpression, context, typeResolver);
242            OverloadResolutionResults<CallableDescriptor> overloadResolutionResults =
243                    CallableReferencesResolutionUtilsKt.resolvePossiblyAmbiguousCallableReference(
244                            callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS,
245                            callResolver);
246            return CallableReferencesResolutionUtilsKt.getResolvedCallableReferenceShapeType(
247                    callableReferenceExpression, receiverType, overloadResolutionResults, context, expectedTypeIsUnknown,
248                    reflectionTypes, builtIns, functionPlaceholders);
249        }
250    
251        @NotNull
252        public KotlinTypeInfo getFunctionLiteralTypeInfo(
253                @NotNull KtExpression expression,
254                @NotNull KtFunction functionLiteral,
255                @NotNull CallResolutionContext<?> context,
256                @NotNull ResolveArgumentsMode resolveArgumentsMode
257        ) {
258            if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
259                KotlinType type = getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, true);
260                return TypeInfoFactoryKt.createTypeInfo(type, context);
261            }
262            return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
263        }
264    
265        @Nullable
266        public KotlinType getShapeTypeOfFunctionLiteral(
267                @NotNull KtFunction function,
268                @NotNull LexicalScope scope,
269                @NotNull BindingTrace trace,
270                boolean expectedTypeIsUnknown
271        ) {
272            boolean isFunctionLiteral = function instanceof KtFunctionLiteral;
273            if (function.getValueParameterList() == null && isFunctionLiteral) {
274                return expectedTypeIsUnknown
275                       ? functionPlaceholders
276                               .createFunctionPlaceholderType(Collections.<KotlinType>emptyList(), /* hasDeclaredArguments = */ false)
277                       : builtIns.getFunctionType(Annotations.Companion.getEMPTY(), null, Collections.<KotlinType>emptyList(), DONT_CARE);
278            }
279            List<KtParameter> valueParameters = function.getValueParameters();
280            TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
281                    trace, "trace to resolve function literal parameter types");
282            List<KotlinType> parameterTypes = Lists.newArrayList();
283            for (KtParameter parameter : valueParameters) {
284                parameterTypes.add(resolveTypeRefWithDefault(parameter.getTypeReference(), scope, temporaryTrace, DONT_CARE));
285            }
286            KotlinType returnType = resolveTypeRefWithDefault(function.getTypeReference(), scope, temporaryTrace, DONT_CARE);
287            assert returnType != null;
288            KotlinType receiverType = resolveTypeRefWithDefault(function.getReceiverTypeReference(), scope, temporaryTrace, null);
289    
290            return expectedTypeIsUnknown && isFunctionLiteral
291                   ? functionPlaceholders.createFunctionPlaceholderType(parameterTypes, /* hasDeclaredArguments = */ true)
292                   : builtIns.getFunctionType(Annotations.Companion.getEMPTY(), receiverType, parameterTypes, returnType);
293        }
294    
295        @Nullable
296        public KotlinType resolveTypeRefWithDefault(
297                @Nullable KtTypeReference returnTypeRef,
298                @NotNull LexicalScope scope,
299                @NotNull BindingTrace trace,
300                @Nullable KotlinType defaultValue
301        ) {
302            if (returnTypeRef != null) {
303                return typeResolver.resolveType(scope, returnTypeRef, trace, true);
304            }
305            return defaultValue;
306        }
307    
308        /**
309         * Visits function call arguments and determines data flow information changes
310         */
311        public void analyzeArgumentsAndRecordTypes(
312                @NotNull CallResolutionContext<?> context
313        ) {
314            MutableDataFlowInfoForArguments infoForArguments = context.dataFlowInfoForArguments;
315            Call call = context.call;
316            infoForArguments.setInitialDataFlowInfo(context.dataFlowInfo);
317    
318            for (ValueArgument argument : call.getValueArguments()) {
319                KtExpression expression = argument.getArgumentExpression();
320                if (expression == null) continue;
321    
322                CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument));
323                // Here we go inside arguments and determine additional data flow information for them
324                KotlinTypeInfo typeInfoForCall = getArgumentTypeInfo(expression, newContext, SHAPE_FUNCTION_ARGUMENTS);
325                infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
326            }
327        }
328    
329        @Nullable
330        public KotlinType updateResultArgumentTypeIfNotDenotable(
331                @NotNull ResolutionContext context,
332                @NotNull KtExpression expression
333        ) {
334            KotlinType type = context.trace.getType(expression);
335            if (type != null && !type.getConstructor().isDenotable()) {
336                if (type.getConstructor() instanceof IntegerValueTypeConstructor) {
337                    IntegerValueTypeConstructor constructor = (IntegerValueTypeConstructor) type.getConstructor();
338                    KotlinType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, context.expectedType);
339                    constantExpressionEvaluator.updateNumberType(primitiveType, expression, context.statementFilter, context.trace);
340                    return primitiveType;
341                }
342            }
343            return null;
344        }
345    }