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