diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt index 36f26dfe09a..4622b1d88db 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt @@ -65,18 +65,19 @@ internal class KtFirCallResolver( val accessorSymbol = analysisSession.firSymbolBuilder.functionLikeBuilder.buildFunctionLikeSymbol(accessor) val target = if (!access.isWrite || setterValue != null) - KtSuccessCallTarget(accessorSymbol) + KtSuccessCallTarget(accessorSymbol, token) else // access.isWrite && setterValue == null KtErrorCallTarget( listOf(accessorSymbol), - KtNonBoundToPsiErrorDiagnostic(factoryName = null, "Setter value is missing", token) + KtNonBoundToPsiErrorDiagnostic(factoryName = null, "Setter value is missing", token), + token ) val ktArgumentMapping = LinkedHashMap() if (access.isWrite && setterValue != null) { val setterParameterSymbol = accessor.valueParameters.single().buildSymbol(firSymbolBuilder) as KtValueParameterSymbol ktArgumentMapping[setterValue] = setterParameterSymbol } - return KtFunctionCall(ktArgumentMapping, target) + return KtFunctionCall(ktArgumentMapping, target, token) } else -> return null } @@ -166,7 +167,7 @@ internal class KtFirCallResolver( is FirResolvedNamedReference -> { val functionSymbol = callReference.resolvedSymbol as? FirNamedFunctionSymbol (functionSymbol?.fir?.buildSymbol(firSymbolBuilder) as? KtFunctionSymbol)?.let { - functionSymbol to KtSuccessCallTarget(it) + functionSymbol to KtSuccessCallTarget(it, token) } ?: return null } is FirErrorNamedReference -> { @@ -177,26 +178,26 @@ internal class KtFirCallResolver( } val callableId = functionSymbol?.callableId ?: return null return if (callableId in kotlinFunctionInvokeCallableIds) { - KtFunctionalTypeVariableCall(variableLikeSymbol, createArgumentMapping(), target) + KtFunctionalTypeVariableCall(variableLikeSymbol, createArgumentMapping(), target, token) } else { - KtVariableWithInvokeFunctionCall(variableLikeSymbol, createArgumentMapping(), target) + KtVariableWithInvokeFunctionCall(variableLikeSymbol, createArgumentMapping(), target, token) } } private fun FirFunctionCall.asSimpleFunctionCall(): KtFunctionCall? { val target = calleeReference.createCallTarget() ?: return null - return KtFunctionCall(createArgumentMapping(), target) + return KtFunctionCall(createArgumentMapping(), target, token) } private fun FirAnnotationCall.asAnnotationCall(): KtAnnotationCall? { val target = calleeReference.createCallTarget() ?: return null - return KtAnnotationCall(createArgumentMapping(), target) + return KtAnnotationCall(createArgumentMapping(), target, token) } private fun FirDelegatedConstructorCall.asDelegatedConstructorCall(): KtDelegatedConstructorCall? { val target = calleeReference.createCallTarget() ?: return null val kind = if (isSuper) KtDelegatedConstructorCallKind.SUPER_CALL else KtDelegatedConstructorCallKind.THIS_CALL - return KtDelegatedConstructorCall(createArgumentMapping(), target, kind) + return KtDelegatedConstructorCall(createArgumentMapping(), target, kind, token) } private fun FirConstructor.asDelegatedConstructorCall(): KtDelegatedConstructorCall? { @@ -214,7 +215,7 @@ internal class KtFirCallResolver( private fun FirReference.createCallTarget(): KtCallTarget? { return when (this) { is FirSuperReference -> createCallTarget(source) - is FirResolvedNamedReference -> getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it) } + is FirResolvedNamedReference -> getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it, token) } is FirErrorNamedReference -> createErrorCallTarget(source) is FirErrorReferenceWithCandidate -> createErrorCallTarget(source) is FirSimpleNamedReference -> @@ -285,15 +286,13 @@ internal class KtFirCallResolver( KtErrorCallTarget( getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol }, source?.let { diagnostic.asKtDiagnostic(it, qualifiedAccessSource, diagnosticCache) } - ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token) - ) + ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token), token) private fun FirErrorReferenceWithCandidate.createErrorCallTarget(qualifiedAccessSource: FirSourceElement?): KtErrorCallTarget = KtErrorCallTarget( getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol }, source?.let { diagnostic.asKtDiagnostic(it, qualifiedAccessSource, diagnosticCache) } - ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token) - ) + ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, diagnostic.reason, token), token) private fun FirResolvedNamedReference.getKtFunctionOrConstructorSymbol(): KtFunctionLikeSymbol? = resolvedSymbol.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol @@ -306,12 +305,11 @@ internal class KtFirCallResolver( analysisSession.getPrimaryConstructor(it)?.let { ctor -> listOf(ctor) } } ?: emptyList(), source?.let { type.diagnostic.asKtDiagnostic(it, qualifiedAccessSource, diagnosticCache) } - ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, type.diagnostic.reason, token) - ) + ?: KtNonBoundToPsiErrorDiagnostic(factoryName = null, type.diagnostic.reason, token), token) is ConeClassLikeType -> type.classId?.let { classId -> (firSymbolBuilder.classifierBuilder.buildClassLikeSymbolByClassId(classId) as? KtSymbolWithMembers)?.let { - analysisSession.getPrimaryConstructor(it)?.let { ctor -> KtSuccessCallTarget(ctor) } + analysisSession.getPrimaryConstructor(it)?.let { ctor -> KtSuccessCallTarget(ctor, token) } } } else -> diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractResolveCallTest.kt b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractResolveCallTest.kt index 9e81d205a58..662127e619a 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractResolveCallTest.kt +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/AbstractResolveCallTest.kt @@ -87,11 +87,15 @@ private fun KtCall.stringRepresentation(): String { return buildString { append(callInfoClass.simpleName!!) append(":\n") - val propertyByName = callInfoClass.memberProperties.associateBy(KProperty1<*, *>::name) - callInfoClass.primaryConstructor!!.parameters.joinTo(this, separator = "\n") { parameter -> - val value = propertyByName[parameter.name]!!.javaGetter!!(this@stringRepresentation)?.stringValue() - "${parameter.name!!} = $value" - } + val propertyByName = + callInfoClass.memberProperties.associateBy(KProperty1<*, *>::name) + callInfoClass.primaryConstructor!!.parameters + .filter { it.name != "token" } + .joinTo(this, separator = "\n") { parameter -> + val name = parameter.name!!.removePrefix("_") + val value = propertyByName[name]!!.javaGetter!!(this@stringRepresentation)?.stringValue() + "$name = $value" + } } } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/KtCall.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/KtCall.kt index 857eb10569d..988ce1a53c1 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/KtCall.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/calls/KtCall.kt @@ -5,16 +5,19 @@ package org.jetbrains.kotlin.analysis.api.calls +import org.jetbrains.kotlin.analysis.api.ValidityTokenOwner import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol +import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken +import org.jetbrains.kotlin.analysis.api.withValidityAssertion import org.jetbrains.kotlin.psi.KtExpression /** * Represents direct or indirect (via invoke) function call from Kotlin code */ -public sealed class KtCall { +public sealed class KtCall : ValidityTokenOwner { public abstract val isErrorCall: Boolean public abstract val argumentMapping: LinkedHashMap public abstract val targetFunction: KtCallTarget @@ -28,11 +31,17 @@ public sealed class KtCall { * } */ public class KtFunctionalTypeVariableCall( - public val target: KtVariableLikeSymbol, - override val argumentMapping: LinkedHashMap, - override val targetFunction: KtCallTarget + private val _target: KtVariableLikeSymbol, + private val _argumentMapping: LinkedHashMap, + private val _targetFunction: KtCallTarget, + override val token: ValidityToken ) : KtCall() { - override val isErrorCall: Boolean get() = false + public val target: KtVariableLikeSymbol get() = withValidityAssertion { _target } + override val isErrorCall: Boolean get() = withValidityAssertion { false } + override val argumentMapping: LinkedHashMap + get() = withValidityAssertion { _argumentMapping } + override val targetFunction: KtCallTarget + get() = withValidityAssertion { _targetFunction } } /** @@ -40,7 +49,7 @@ public class KtFunctionalTypeVariableCall( */ public sealed class KtDeclaredFunctionCall : KtCall() { override val isErrorCall: Boolean - get() = targetFunction is KtErrorCallTarget + get() = withValidityAssertion { targetFunction is KtErrorCallTarget } } /** @@ -54,9 +63,15 @@ public sealed class KtDeclaredFunctionCall : KtCall() { */ public class KtVariableWithInvokeFunctionCall( public val target: KtVariableLikeSymbol, - override val argumentMapping: LinkedHashMap, + private val _argumentMapping: LinkedHashMap, + private val _targetFunction: KtCallTarget, + override val token: ValidityToken +) : KtDeclaredFunctionCall() { + override val argumentMapping: LinkedHashMap + get() = withValidityAssertion { _argumentMapping } override val targetFunction: KtCallTarget -) : KtDeclaredFunctionCall() + get() = withValidityAssertion { _targetFunction } +} /** * Simple function call, e.g., @@ -64,9 +79,15 @@ public class KtVariableWithInvokeFunctionCall( * x.toString() // function call */ public class KtFunctionCall( - override val argumentMapping: LinkedHashMap, + private val _argumentMapping: LinkedHashMap, + private val _targetFunction: KtCallTarget, + override val token: ValidityToken +) : KtDeclaredFunctionCall() { + override val argumentMapping: LinkedHashMap + get() = withValidityAssertion { _argumentMapping } override val targetFunction: KtCallTarget -) : KtDeclaredFunctionCall() + get() = withValidityAssertion { _targetFunction } +} /** * Annotation call, e.g., @@ -75,9 +96,15 @@ public class KtFunctionCall( * annotation class Ann */ public class KtAnnotationCall( - override val argumentMapping: LinkedHashMap, + private val _argumentMapping: LinkedHashMap, + private val _targetFunction: KtCallTarget, + override val token: ValidityToken +) : KtDeclaredFunctionCall() { + override val argumentMapping: LinkedHashMap + get() = withValidityAssertion { _argumentMapping } override val targetFunction: KtCallTarget -) : KtDeclaredFunctionCall() + get() = withValidityAssertion { _targetFunction } +} // TODO: Add other properties, e.g., useSiteTarget /** @@ -89,10 +116,16 @@ public class KtAnnotationCall( * } */ public class KtDelegatedConstructorCall( - override val argumentMapping: LinkedHashMap, - override val targetFunction: KtCallTarget, - public val kind: KtDelegatedConstructorCallKind -) : KtDeclaredFunctionCall() + private val _argumentMapping: LinkedHashMap, + private val _targetFunction: KtCallTarget, + public val kind: KtDelegatedConstructorCallKind, + override val token: ValidityToken +) : KtDeclaredFunctionCall() { + override val argumentMapping: LinkedHashMap + get() = withValidityAssertion { _argumentMapping } + override val targetFunction: KtCallTarget + get() = withValidityAssertion { _targetFunction } +} public enum class KtDelegatedConstructorCallKind { SUPER_CALL, THIS_CALL } @@ -101,22 +134,26 @@ public enum class KtDelegatedConstructorCallKind { SUPER_CALL, THIS_CALL } * Can be success [KtSuccessCallTarget] in this case there only one such function * Or erroneous [KtErrorCallTarget] in this case there can be any count of candidates */ -public sealed class KtCallTarget { +public sealed class KtCallTarget : ValidityTokenOwner { public abstract val candidates: Collection } /** * Success call of [symbol] */ -public class KtSuccessCallTarget(public val symbol: KtFunctionLikeSymbol) : KtCallTarget() { - override val candidates: Collection - get() = listOf(symbol) +public class KtSuccessCallTarget(private val _symbol: KtFunctionLikeSymbol, override val token: ValidityToken) : KtCallTarget() { + public val symbol: KtFunctionLikeSymbol get() = withValidityAssertion { _symbol } + override val candidates: Collection get() = withValidityAssertion { listOf(symbol) } } /** - * Function all with errors, possible candidates are [candidates] + * Function call with errors, possible candidates are [candidates] */ public class KtErrorCallTarget( - override val candidates: Collection, - public val diagnostic: KtDiagnostic -) : KtCallTarget() \ No newline at end of file + private val _candidates: Collection, + private val _diagnostic: KtDiagnostic, + override val token: ValidityToken +) : KtCallTarget() { + public val diagnostic: KtDiagnostic get() = withValidityAssertion { _diagnostic } + override val candidates: Collection get() = withValidityAssertion { _candidates } +} \ No newline at end of file