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