[NI] Don't forget to analyze whole block for last postponed expression
This commit is contained in:
@@ -106,10 +106,11 @@ class LambdaKotlinCallArgumentImpl(
|
||||
dataFlowInfoBeforeThisArgument: DataFlowInfo,
|
||||
argumentName: Name?,
|
||||
val ktLambdaExpression: KtLambdaExpression,
|
||||
val containingBlockForLambda: KtExpression,
|
||||
override val parametersTypes: Array<UnwrappedType?>?
|
||||
) : PSIFunctionKotlinCallArgument(outerCallContext, valueArgument, dataFlowInfoBeforeThisArgument, argumentName) {
|
||||
override val ktFunction get() = ktLambdaExpression.functionLiteral
|
||||
override val expression get() = ktLambdaExpression
|
||||
override val expression get() = containingBlockForLambda
|
||||
}
|
||||
|
||||
class FunctionExpressionImpl(
|
||||
@@ -117,12 +118,13 @@ class FunctionExpressionImpl(
|
||||
valueArgument: ValueArgument,
|
||||
dataFlowInfoBeforeThisArgument: DataFlowInfo,
|
||||
argumentName: Name?,
|
||||
val containingBlockForFunction: KtExpression,
|
||||
override val ktFunction: KtNamedFunction,
|
||||
override val receiverType: UnwrappedType?,
|
||||
override val parametersTypes: Array<UnwrappedType?>,
|
||||
override val returnType: UnwrappedType?
|
||||
) : FunctionExpression, PSIFunctionKotlinCallArgument(outerCallContext, valueArgument, dataFlowInfoBeforeThisArgument, argumentName) {
|
||||
override val expression get() = ktFunction
|
||||
override val expression get() = containingBlockForFunction
|
||||
}
|
||||
|
||||
class CallableReferenceKotlinCallArgumentImpl(
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.contracts.EffectSystem
|
||||
@@ -521,27 +522,14 @@ class PSICallResolver(
|
||||
): PSIKotlinCallArgument {
|
||||
val builtIns = outerCallContext.scope.ownerDescriptor.builtIns
|
||||
val parseErrorArgument = ParseErrorKotlinCallArgument(valueArgument, startDataFlowInfo, builtIns)
|
||||
val ktExpression = extractArgumentExpression(outerCallContext, valueArgument) ?: parseErrorArgument
|
||||
val argumentExpression = valueArgument.getArgumentExpression() ?: return parseErrorArgument
|
||||
|
||||
val ktExpression = KtPsiUtil.deparenthesize(argumentExpression) ?: parseErrorArgument
|
||||
|
||||
val argumentName = valueArgument.getArgumentName()?.asName
|
||||
|
||||
val lambdaArgument: PSIKotlinCallArgument? = when (ktExpression) {
|
||||
is KtLambdaExpression ->
|
||||
LambdaKotlinCallArgumentImpl(outerCallContext, valueArgument, startDataFlowInfo, argumentName, ktExpression,
|
||||
resolveParametersTypes(outerCallContext, ktExpression.functionLiteral))
|
||||
is KtNamedFunction -> {
|
||||
val receiverType = resolveType(outerCallContext, ktExpression.receiverTypeReference)
|
||||
val parametersTypes = resolveParametersTypes(outerCallContext, ktExpression) ?: emptyArray()
|
||||
val returnType = resolveType(outerCallContext, ktExpression.typeReference) ?:
|
||||
if (ktExpression.hasBlockBody()) builtIns.unitType else null
|
||||
FunctionExpressionImpl(outerCallContext, valueArgument, startDataFlowInfo, argumentName, ktExpression, receiverType, parametersTypes, returnType)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
if (lambdaArgument != null) {
|
||||
checkNoSpread(outerCallContext, valueArgument)
|
||||
return lambdaArgument
|
||||
processFunctionalExpression(outerCallContext, argumentExpression, startDataFlowInfo, valueArgument, argumentName, builtIns)?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
if (ktExpression is KtCollectionLiteralExpression) {
|
||||
@@ -596,24 +584,43 @@ class PSICallResolver(
|
||||
ktExpression, argumentName, lhsNewResult, name)
|
||||
}
|
||||
|
||||
val argumentExpression = valueArgument.getArgumentExpression() ?: return parseErrorArgument
|
||||
|
||||
// argumentExpression instead of ktExpression is hack -- type info should be stored also for parenthesized expression
|
||||
val typeInfo = expressionTypingServices.getTypeInfo(argumentExpression, context)
|
||||
return createSimplePSICallArgument(context, valueArgument, typeInfo) ?: parseErrorArgument
|
||||
}
|
||||
|
||||
private fun extractArgumentExpression(outerCallContext: BasicCallResolutionContext, valueArgument: ValueArgument): KtExpression? {
|
||||
val argumentExpression = valueArgument.getArgumentExpression() ?: return null
|
||||
private fun processFunctionalExpression(
|
||||
outerCallContext: BasicCallResolutionContext,
|
||||
argumentExpression: KtExpression,
|
||||
startDataFlowInfo: DataFlowInfo,
|
||||
valueArgument: ValueArgument,
|
||||
argumentName: Name?,
|
||||
builtIns: KotlinBuiltIns
|
||||
): PSIKotlinCallArgument? {
|
||||
val expression = ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(argumentExpression, outerCallContext) ?: return null
|
||||
val postponedExpression = if (expression is KtFunctionLiteral) expression.getParentOfType<KtLambdaExpression>(true) else expression
|
||||
|
||||
val ktExpression = ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(argumentExpression, outerCallContext) ?:
|
||||
ArgumentTypeResolver.getCallableReferenceExpressionIfAny(argumentExpression, outerCallContext) ?:
|
||||
KtPsiUtil.deparenthesize(argumentExpression)
|
||||
val lambdaArgument: PSIKotlinCallArgument? = when (postponedExpression) {
|
||||
is KtLambdaExpression ->
|
||||
LambdaKotlinCallArgumentImpl(outerCallContext, valueArgument, startDataFlowInfo, argumentName, postponedExpression,
|
||||
argumentExpression, resolveParametersTypes(outerCallContext, postponedExpression.functionLiteral))
|
||||
|
||||
return when (ktExpression) {
|
||||
is KtFunctionLiteral -> ktExpression.getParentOfType<KtLambdaExpression>(true)
|
||||
else -> ktExpression
|
||||
is KtNamedFunction -> {
|
||||
val receiverType = resolveType(outerCallContext, postponedExpression.receiverTypeReference)
|
||||
val parametersTypes = resolveParametersTypes(outerCallContext, postponedExpression) ?: emptyArray()
|
||||
val returnType = resolveType(outerCallContext, postponedExpression.typeReference) ?:
|
||||
if (postponedExpression.hasBlockBody()) builtIns.unitType else null
|
||||
|
||||
FunctionExpressionImpl(outerCallContext, valueArgument, startDataFlowInfo, argumentName,
|
||||
argumentExpression, postponedExpression, receiverType, parametersTypes, returnType)
|
||||
}
|
||||
|
||||
else -> return null
|
||||
}
|
||||
|
||||
checkNoSpread(outerCallContext, valueArgument)
|
||||
|
||||
return lambdaArgument
|
||||
}
|
||||
|
||||
private fun checkNoSpread(context: BasicCallResolutionContext, valueArgument: ValueArgument) {
|
||||
@@ -629,6 +636,4 @@ class PSICallResolver(
|
||||
parameterList.parameters[it]?.typeReference?.let { resolveType(context, it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// !CHECK_TYPE
|
||||
|
||||
import kotlin.reflect.KFunction0
|
||||
|
||||
fun test() {
|
||||
val a = if (true) {
|
||||
val x = 1
|
||||
"".length
|
||||
::foo
|
||||
} else {
|
||||
::foo
|
||||
}
|
||||
a checkType { _<KFunction0<Int>>() }
|
||||
}
|
||||
|
||||
fun foo(): Int = 0
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Int
|
||||
public fun test(): kotlin.Unit
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION
|
||||
|
||||
import java.util.HashSet
|
||||
|
||||
fun test123() {
|
||||
val g: (Int) -> Unit = if (true) {
|
||||
val set = HashSet<Int>()
|
||||
fun (i: Int) {
|
||||
set.add(i)
|
||||
}
|
||||
}
|
||||
else {
|
||||
{ it -> it }
|
||||
}
|
||||
}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun test123(): kotlin.Unit
|
||||
+3
-4
@@ -1,11 +1,10 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !CHECK_TYPE
|
||||
fun test() {
|
||||
val a = if (true) {
|
||||
val x = 1
|
||||
({ <!NI;UNRESOLVED_REFERENCE!>x<!> })
|
||||
({ x })
|
||||
} else {
|
||||
{ <!NI;UNUSED_EXPRESSION!>2<!> }
|
||||
{ 2 }
|
||||
}
|
||||
<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a<!> <!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>checkType<!> { <!NI;UNRESOLVED_REFERENCE!>_<!><() -> Int>() }
|
||||
a checkType { _<() -> Int>() }
|
||||
}
|
||||
+2
-3
@@ -1,13 +1,12 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION
|
||||
|
||||
import java.util.HashSet
|
||||
|
||||
fun test123() {
|
||||
val g: (Int) -> Unit = if (true) {
|
||||
val set = <!NI;DEBUG_INFO_MISSING_UNRESOLVED!>HashSet<!><<!NI;DEBUG_INFO_MISSING_UNRESOLVED!>Int<!>>();
|
||||
val set = HashSet<Int>();
|
||||
{ i ->
|
||||
<!NI;UNRESOLVED_REFERENCE!>set<!>.<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>add<!>(i)
|
||||
set.add(i)
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1858,6 +1858,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferenceAsLastExpressionInBlock.kt")
|
||||
public void testCallableReferenceAsLastExpressionInBlock() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/callableReferenceAsLastExpressionInBlock.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classVsPackage.kt")
|
||||
public void testClassVsPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/classVsPackage.kt");
|
||||
@@ -8422,6 +8428,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionExpressionAsLastExpressionInBlock.kt")
|
||||
public void testFunctionExpressionAsLastExpressionInBlock() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/functionExpressionAsLastExpressionInBlock.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionLIteralInBlockInIf.kt")
|
||||
public void testFunctionLIteralInBlockInIf() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/functionLIteralInBlockInIf.kt");
|
||||
|
||||
+12
@@ -1858,6 +1858,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferenceAsLastExpressionInBlock.kt")
|
||||
public void testCallableReferenceAsLastExpressionInBlock() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/callableReferenceAsLastExpressionInBlock.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classVsPackage.kt")
|
||||
public void testClassVsPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/classVsPackage.kt");
|
||||
@@ -8422,6 +8428,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionExpressionAsLastExpressionInBlock.kt")
|
||||
public void testFunctionExpressionAsLastExpressionInBlock() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/functionExpressionAsLastExpressionInBlock.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionLIteralInBlockInIf.kt")
|
||||
public void testFunctionLIteralInBlockInIf() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/functionLIteralInBlockInIf.kt");
|
||||
|
||||
Reference in New Issue
Block a user