[NI] Add common supertype for PSI lambda arguments
Also move initial dataFlowInfo to lambda arguments. As result, we can not store outer call for postpone call arguments
This commit is contained in:
+6
-15
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.KtReturnExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
||||
@@ -69,31 +68,23 @@ class KotlinResolutionCallbacksImpl(
|
||||
}
|
||||
|
||||
override fun analyzeAndGetLambdaResultArguments(
|
||||
outerCall: KotlinCall,
|
||||
lambdaArgument: LambdaKotlinCallArgument,
|
||||
isSuspend: Boolean,
|
||||
receiverType: UnwrappedType?,
|
||||
parameters: List<UnwrappedType>,
|
||||
expectedReturnType: UnwrappedType?
|
||||
): List<SimpleKotlinCallArgument> {
|
||||
val psiCallArgument = lambdaArgument.psiCallArgument
|
||||
val outerCallContext = (psiCallArgument as? LambdaKotlinCallArgumentImpl)?.outerCallContext ?:
|
||||
(psiCallArgument as FunctionExpressionImpl).outerCallContext
|
||||
val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument
|
||||
val outerCallContext = psiCallArgument.outerCallContext
|
||||
|
||||
fun createCallArgument(ktExpression: KtExpression, typeInfo: KotlinTypeInfo) =
|
||||
createSimplePSICallArgument(trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor,
|
||||
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo)
|
||||
|
||||
val expression: KtExpression = (psiCallArgument as? LambdaKotlinCallArgumentImpl)?.ktLambdaExpression ?:
|
||||
(psiCallArgument as FunctionExpressionImpl).ktFunction
|
||||
|
||||
val ktFunction: KtFunction = (psiCallArgument as? LambdaKotlinCallArgumentImpl)?.ktLambdaExpression?.functionLiteral ?:
|
||||
(psiCallArgument as FunctionExpressionImpl).ktFunction
|
||||
|
||||
val lambdaInfo = LambdaInfo(expectedReturnType ?: TypeUtils.NO_EXPECTED_TYPE,
|
||||
if (expectedReturnType == null) ContextDependency.DEPENDENT else ContextDependency.INDEPENDENT)
|
||||
|
||||
trace.record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, ktFunction, lambdaInfo)
|
||||
trace.record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, psiCallArgument.ktFunction, lambdaInfo)
|
||||
|
||||
val builtIns = outerCallContext.scope.ownerDescriptor.builtIns
|
||||
val expectedType = createFunctionType(builtIns, Annotations.EMPTY, receiverType, parameters, null,
|
||||
@@ -105,10 +96,10 @@ class KotlinResolutionCallbacksImpl(
|
||||
.replaceBindingTrace(trace)
|
||||
.replaceContextDependency(lambdaInfo.contextDependency)
|
||||
.replaceExpectedType(approximatesExpectedType)
|
||||
.replaceDataFlowInfo(outerCall.psiKotlinCall.resultDataFlowInfo)
|
||||
.replaceDataFlowInfo(psiCallArgument.lambdaInitialDataFlowInfo)
|
||||
|
||||
val functionTypeInfo = expressionTypingServices.getTypeInfo(expression, actualContext)
|
||||
trace.record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, ktFunction, LambdaInfo.STUB_EMPTY)
|
||||
val functionTypeInfo = expressionTypingServices.getTypeInfo(psiCallArgument.expression, actualContext)
|
||||
trace.record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, psiCallArgument.ktFunction, LambdaInfo.STUB_EMPTY)
|
||||
|
||||
var hasReturnWithoutExpression = false
|
||||
val returnArguments = lambdaInfo.returnStatements.mapNotNullTo(ArrayList()) { (expression, typeInfo) ->
|
||||
|
||||
+33
-13
@@ -81,30 +81,43 @@ class ParseErrorKotlinCallArgument(
|
||||
get() = dataFlowInfoAfterThisArgument
|
||||
}
|
||||
|
||||
class LambdaKotlinCallArgumentImpl(
|
||||
abstract class PSIFunctionKotlinCallArgument(
|
||||
val outerCallContext: BasicCallResolutionContext,
|
||||
override val valueArgument: ValueArgument,
|
||||
override val dataFlowInfoBeforeThisArgument: DataFlowInfo,
|
||||
val ktLambdaExpression: KtLambdaExpression,
|
||||
override val argumentName: Name?,
|
||||
override val parametersTypes: Array<UnwrappedType?>?
|
||||
override val argumentName: Name?
|
||||
) : LambdaKotlinCallArgument, PSIKotlinCallArgument() {
|
||||
override val dataFlowInfoAfterThisArgument: DataFlowInfo
|
||||
override val dataFlowInfoAfterThisArgument: DataFlowInfo // todo drop this and use only lambdaInitialDataFlowInfo
|
||||
get() = dataFlowInfoBeforeThisArgument
|
||||
|
||||
abstract val ktFunction: KtFunction
|
||||
abstract val expression: KtExpression
|
||||
lateinit var lambdaInitialDataFlowInfo: DataFlowInfo
|
||||
}
|
||||
|
||||
class LambdaKotlinCallArgumentImpl(
|
||||
outerCallContext: BasicCallResolutionContext,
|
||||
valueArgument: ValueArgument,
|
||||
dataFlowInfoBeforeThisArgument: DataFlowInfo,
|
||||
argumentName: Name?,
|
||||
val ktLambdaExpression: KtLambdaExpression,
|
||||
override val parametersTypes: Array<UnwrappedType?>?
|
||||
) : PSIFunctionKotlinCallArgument(outerCallContext, valueArgument, dataFlowInfoBeforeThisArgument, argumentName) {
|
||||
override val ktFunction get() = ktLambdaExpression.functionLiteral
|
||||
override val expression get() = ktLambdaExpression
|
||||
}
|
||||
|
||||
class FunctionExpressionImpl(
|
||||
val outerCallContext: BasicCallResolutionContext,
|
||||
override val valueArgument: ValueArgument,
|
||||
override val dataFlowInfoBeforeThisArgument: DataFlowInfo,
|
||||
val ktFunction: KtNamedFunction,
|
||||
override val argumentName: Name?,
|
||||
outerCallContext: BasicCallResolutionContext,
|
||||
valueArgument: ValueArgument,
|
||||
dataFlowInfoBeforeThisArgument: DataFlowInfo,
|
||||
argumentName: Name?,
|
||||
override val ktFunction: KtNamedFunction,
|
||||
override val receiverType: UnwrappedType?,
|
||||
override val parametersTypes: Array<UnwrappedType?>,
|
||||
override val returnType: UnwrappedType?
|
||||
) : FunctionExpression, PSIKotlinCallArgument() {
|
||||
override val dataFlowInfoAfterThisArgument: DataFlowInfo
|
||||
get() = dataFlowInfoBeforeThisArgument
|
||||
) : FunctionExpression, PSIFunctionKotlinCallArgument(outerCallContext, valueArgument, dataFlowInfoBeforeThisArgument, argumentName) {
|
||||
override val expression get() = ktFunction
|
||||
}
|
||||
|
||||
class CallableReferenceKotlinCallArgumentImpl(
|
||||
@@ -171,6 +184,13 @@ class EmptyLabeledReturn(
|
||||
override val isSafeCall: Boolean get() = false
|
||||
}
|
||||
|
||||
internal fun KotlinCallArgument.setResultDataFlowInfoIfRelevant(resultDataFlowInfo: DataFlowInfo) {
|
||||
if (this is PSIFunctionKotlinCallArgument) {
|
||||
lambdaInitialDataFlowInfo = resultDataFlowInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// context here is context for value argument analysis
|
||||
internal fun createSimplePSICallArgument(
|
||||
contextForArgument: BasicCallResolutionContext,
|
||||
|
||||
@@ -423,6 +423,9 @@ class PSICallResolver(
|
||||
val astExternalArgument = externalArgument?.let { resolveValueArgument(context, dataFlowInfoAfterArgumentsInParenthesis, it) }
|
||||
val resultDataFlowInfo = astExternalArgument?.dataFlowInfoAfterThisArgument ?: dataFlowInfoAfterArgumentsInParenthesis
|
||||
|
||||
resolvedArgumentsInParenthesis.forEach { it.setResultDataFlowInfoIfRelevant(resultDataFlowInfo) }
|
||||
astExternalArgument?.setResultDataFlowInfoIfRelevant(resultDataFlowInfo)
|
||||
|
||||
return PSIKotlinCallImpl(kotlinCallKind, oldCall, tracingStrategy, resolvedExplicitReceiver, name, resolvedTypeArguments, resolvedArgumentsInParenthesis,
|
||||
astExternalArgument, context.dataFlowInfo, resultDataFlowInfo, context.dataFlowInfoForArguments)
|
||||
}
|
||||
@@ -501,14 +504,14 @@ class PSICallResolver(
|
||||
|
||||
val lambdaArgument: PSIKotlinCallArgument? = when (ktExpression) {
|
||||
is KtLambdaExpression ->
|
||||
LambdaKotlinCallArgumentImpl(outerCallContext, valueArgument, startDataFlowInfo, ktExpression, argumentName,
|
||||
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, ktExpression, argumentName, receiverType, parametersTypes, returnType)
|
||||
FunctionExpressionImpl(outerCallContext, valueArgument, startDataFlowInfo, argumentName, ktExpression, receiverType, parametersTypes, returnType)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user