Typecheck call arguments if callee is resolved to variable

#KT-11579 Fixed
This commit is contained in:
Pavel V. Talanov
2016-04-04 15:45:18 +03:00
parent e46d713bba
commit 3f62b6c495
6 changed files with 34 additions and 4 deletions
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * Copyright 2010-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -315,7 +315,7 @@ public class ArgumentTypeResolver {
* Visits function call arguments and determines data flow information changes * Visits function call arguments and determines data flow information changes
*/ */
public void analyzeArgumentsAndRecordTypes( public void analyzeArgumentsAndRecordTypes(
@NotNull CallResolutionContext<?> context @NotNull CallResolutionContext<?> context, @NotNull ResolveArgumentsMode resolveArgumentsMode
) { ) {
MutableDataFlowInfoForArguments infoForArguments = context.dataFlowInfoForArguments; MutableDataFlowInfoForArguments infoForArguments = context.dataFlowInfoForArguments;
Call call = context.call; Call call = context.call;
@@ -326,7 +326,7 @@ public class ArgumentTypeResolver {
CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument)); CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument));
// Here we go inside arguments and determine additional data flow information for them // Here we go inside arguments and determine additional data flow information for them
KotlinTypeInfo typeInfoForCall = getArgumentTypeInfo(expression, newContext, SHAPE_FUNCTION_ARGUMENTS); KotlinTypeInfo typeInfoForCall = getArgumentTypeInfo(expression, newContext, resolveArgumentsMode);
infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo()); infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
} }
} }
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.bindingContextUtil.recordDataFlowInfo import org.jetbrains.kotlin.resolve.bindingContextUtil.recordDataFlowInfo
import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScope import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScope
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
@@ -64,6 +65,7 @@ import javax.inject.Inject
class CallExpressionResolver( class CallExpressionResolver(
private val callResolver: CallResolver, private val callResolver: CallResolver,
private val constantExpressionEvaluator: ConstantExpressionEvaluator, private val constantExpressionEvaluator: ConstantExpressionEvaluator,
private val argumentTypeResolver: ArgumentTypeResolver,
private val dataFlowAnalyzer: DataFlowAnalyzer, private val dataFlowAnalyzer: DataFlowAnalyzer,
private val builtIns: KotlinBuiltIns, private val builtIns: KotlinBuiltIns,
private val qualifiedExpressionResolver: QualifiedExpressionResolver, private val qualifiedExpressionResolver: QualifiedExpressionResolver,
@@ -247,6 +249,13 @@ class CallExpressionResolver(
temporaryForVariable.commit() temporaryForVariable.commit()
context.trace.report(FUNCTION_EXPECTED.on(calleeExpression, calleeExpression, context.trace.report(FUNCTION_EXPECTED.on(calleeExpression, calleeExpression,
type ?: ErrorUtils.createErrorType(""))) type ?: ErrorUtils.createErrorType("")))
argumentTypeResolver.analyzeArgumentsAndRecordTypes(
BasicCallResolutionContext.create(
context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
DataFlowInfoForArgumentsImpl(initialDataFlowInfoForArguments, call)
),
ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS
)
return noTypeInfo(context) return noTypeInfo(context)
} }
} }
@@ -575,7 +575,7 @@ public class CallResolver {
@NotNull TracingStrategy tracing @NotNull TracingStrategy tracing
) { ) {
if (context.checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) { if (context.checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) {
argumentTypeResolver.analyzeArgumentsAndRecordTypes(context); argumentTypeResolver.analyzeArgumentsAndRecordTypes(context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS);
} }
List<KtTypeProjection> typeArguments = context.call.getTypeArguments(); List<KtTypeProjection> typeArguments = context.call.getTypeArguments();
@@ -0,0 +1,4 @@
fun f() {
val g = 3
<error>g</error>(object : Any() {})
}
@@ -0,0 +1,5 @@
fun f() {
val g = 3
<error>g</error> { <error>workingSet</error>, <error>customer</error> ->
}
}
@@ -436,6 +436,18 @@ public class PsiCheckerTestGenerated extends AbstractPsiCheckerTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("callVariableAsFunctionWithAnonymousObjectArg.kt")
public void testCallVariableAsFunctionWithAnonymousObjectArg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/callVariableAsFunctionWithAnonymousObjectArg.kt");
doTest(fileName);
}
@TestMetadata("callVariableAsFunctionWithLambdaArg.kt")
public void testCallVariableAsFunctionWithLambdaArg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/callVariableAsFunctionWithLambdaArg.kt");
doTest(fileName);
}
@TestMetadata("ClassDeclarationAfterDot.kt") @TestMetadata("ClassDeclarationAfterDot.kt")
public void testClassDeclarationAfterDot() throws Exception { public void testClassDeclarationAfterDot() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/ClassDeclarationAfterDot.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/ClassDeclarationAfterDot.kt");