FIR IDE: add validity token to KtCall

This commit is contained in:
Tianyu Geng
2021-08-27 10:43:34 -07:00
committed by Ilya Kirillov
parent 245c4082cd
commit 9f0f1781c9
3 changed files with 85 additions and 46 deletions
@@ -65,18 +65,19 @@ internal class KtFirCallResolver(
val accessorSymbol = analysisSession.firSymbolBuilder.functionLikeBuilder.buildFunctionLikeSymbol(accessor) val accessorSymbol = analysisSession.firSymbolBuilder.functionLikeBuilder.buildFunctionLikeSymbol(accessor)
val target = val target =
if (!access.isWrite || setterValue != null) if (!access.isWrite || setterValue != null)
KtSuccessCallTarget(accessorSymbol) KtSuccessCallTarget(accessorSymbol, token)
else // access.isWrite && setterValue == null else // access.isWrite && setterValue == null
KtErrorCallTarget( KtErrorCallTarget(
listOf(accessorSymbol), listOf(accessorSymbol),
KtNonBoundToPsiErrorDiagnostic(factoryName = null, "Setter value is missing", token) KtNonBoundToPsiErrorDiagnostic(factoryName = null, "Setter value is missing", token),
token
) )
val ktArgumentMapping = LinkedHashMap<KtExpression, KtValueParameterSymbol>() val ktArgumentMapping = LinkedHashMap<KtExpression, KtValueParameterSymbol>()
if (access.isWrite && setterValue != null) { if (access.isWrite && setterValue != null) {
val setterParameterSymbol = accessor.valueParameters.single().buildSymbol(firSymbolBuilder) as KtValueParameterSymbol val setterParameterSymbol = accessor.valueParameters.single().buildSymbol(firSymbolBuilder) as KtValueParameterSymbol
ktArgumentMapping[setterValue] = setterParameterSymbol ktArgumentMapping[setterValue] = setterParameterSymbol
} }
return KtFunctionCall(ktArgumentMapping, target) return KtFunctionCall(ktArgumentMapping, target, token)
} }
else -> return null else -> return null
} }
@@ -166,7 +167,7 @@ internal class KtFirCallResolver(
is FirResolvedNamedReference -> { is FirResolvedNamedReference -> {
val functionSymbol = callReference.resolvedSymbol as? FirNamedFunctionSymbol val functionSymbol = callReference.resolvedSymbol as? FirNamedFunctionSymbol
(functionSymbol?.fir?.buildSymbol(firSymbolBuilder) as? KtFunctionSymbol)?.let { (functionSymbol?.fir?.buildSymbol(firSymbolBuilder) as? KtFunctionSymbol)?.let {
functionSymbol to KtSuccessCallTarget(it) functionSymbol to KtSuccessCallTarget(it, token)
} ?: return null } ?: return null
} }
is FirErrorNamedReference -> { is FirErrorNamedReference -> {
@@ -177,26 +178,26 @@ internal class KtFirCallResolver(
} }
val callableId = functionSymbol?.callableId ?: return null val callableId = functionSymbol?.callableId ?: return null
return if (callableId in kotlinFunctionInvokeCallableIds) { return if (callableId in kotlinFunctionInvokeCallableIds) {
KtFunctionalTypeVariableCall(variableLikeSymbol, createArgumentMapping(), target) KtFunctionalTypeVariableCall(variableLikeSymbol, createArgumentMapping(), target, token)
} else { } else {
KtVariableWithInvokeFunctionCall(variableLikeSymbol, createArgumentMapping(), target) KtVariableWithInvokeFunctionCall(variableLikeSymbol, createArgumentMapping(), target, token)
} }
} }
private fun FirFunctionCall.asSimpleFunctionCall(): KtFunctionCall? { private fun FirFunctionCall.asSimpleFunctionCall(): KtFunctionCall? {
val target = calleeReference.createCallTarget() ?: return null val target = calleeReference.createCallTarget() ?: return null
return KtFunctionCall(createArgumentMapping(), target) return KtFunctionCall(createArgumentMapping(), target, token)
} }
private fun FirAnnotationCall.asAnnotationCall(): KtAnnotationCall? { private fun FirAnnotationCall.asAnnotationCall(): KtAnnotationCall? {
val target = calleeReference.createCallTarget() ?: return null val target = calleeReference.createCallTarget() ?: return null
return KtAnnotationCall(createArgumentMapping(), target) return KtAnnotationCall(createArgumentMapping(), target, token)
} }
private fun FirDelegatedConstructorCall.asDelegatedConstructorCall(): KtDelegatedConstructorCall? { private fun FirDelegatedConstructorCall.asDelegatedConstructorCall(): KtDelegatedConstructorCall? {
val target = calleeReference.createCallTarget() ?: return null val target = calleeReference.createCallTarget() ?: return null
val kind = if (isSuper) KtDelegatedConstructorCallKind.SUPER_CALL else KtDelegatedConstructorCallKind.THIS_CALL 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? { private fun FirConstructor.asDelegatedConstructorCall(): KtDelegatedConstructorCall? {
@@ -214,7 +215,7 @@ internal class KtFirCallResolver(
private fun FirReference.createCallTarget(): KtCallTarget? { private fun FirReference.createCallTarget(): KtCallTarget? {
return when (this) { return when (this) {
is FirSuperReference -> createCallTarget(source) is FirSuperReference -> createCallTarget(source)
is FirResolvedNamedReference -> getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it) } is FirResolvedNamedReference -> getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it, token) }
is FirErrorNamedReference -> createErrorCallTarget(source) is FirErrorNamedReference -> createErrorCallTarget(source)
is FirErrorReferenceWithCandidate -> createErrorCallTarget(source) is FirErrorReferenceWithCandidate -> createErrorCallTarget(source)
is FirSimpleNamedReference -> is FirSimpleNamedReference ->
@@ -285,15 +286,13 @@ internal class KtFirCallResolver(
KtErrorCallTarget( KtErrorCallTarget(
getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol }, getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol },
source?.let { diagnostic.asKtDiagnostic(it, qualifiedAccessSource, diagnosticCache) } 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 = private fun FirErrorReferenceWithCandidate.createErrorCallTarget(qualifiedAccessSource: FirSourceElement?): KtErrorCallTarget =
KtErrorCallTarget( KtErrorCallTarget(
getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol }, getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol },
source?.let { diagnostic.asKtDiagnostic(it, qualifiedAccessSource, diagnosticCache) } 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? = private fun FirResolvedNamedReference.getKtFunctionOrConstructorSymbol(): KtFunctionLikeSymbol? =
resolvedSymbol.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol resolvedSymbol.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol
@@ -306,12 +305,11 @@ internal class KtFirCallResolver(
analysisSession.getPrimaryConstructor(it)?.let { ctor -> listOf(ctor) } analysisSession.getPrimaryConstructor(it)?.let { ctor -> listOf(ctor) }
} ?: emptyList(), } ?: emptyList(),
source?.let { type.diagnostic.asKtDiagnostic(it, qualifiedAccessSource, diagnosticCache) } 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 -> is ConeClassLikeType ->
type.classId?.let { classId -> type.classId?.let { classId ->
(firSymbolBuilder.classifierBuilder.buildClassLikeSymbolByClassId(classId) as? KtSymbolWithMembers)?.let { (firSymbolBuilder.classifierBuilder.buildClassLikeSymbolByClassId(classId) as? KtSymbolWithMembers)?.let {
analysisSession.getPrimaryConstructor(it)?.let { ctor -> KtSuccessCallTarget(ctor) } analysisSession.getPrimaryConstructor(it)?.let { ctor -> KtSuccessCallTarget(ctor, token) }
} }
} }
else -> else ->
@@ -87,11 +87,15 @@ private fun KtCall.stringRepresentation(): String {
return buildString { return buildString {
append(callInfoClass.simpleName!!) append(callInfoClass.simpleName!!)
append(":\n") append(":\n")
val propertyByName = callInfoClass.memberProperties.associateBy(KProperty1<*, *>::name) val propertyByName =
callInfoClass.primaryConstructor!!.parameters.joinTo(this, separator = "\n") { parameter -> callInfoClass.memberProperties.associateBy(KProperty1<*, *>::name)
val value = propertyByName[parameter.name]!!.javaGetter!!(this@stringRepresentation)?.stringValue() callInfoClass.primaryConstructor!!.parameters
"${parameter.name!!} = $value" .filter { it.name != "token" }
} .joinTo(this, separator = "\n") { parameter ->
val name = parameter.name!!.removePrefix("_")
val value = propertyByName[name]!!.javaGetter!!(this@stringRepresentation)?.stringValue()
"$name = $value"
}
} }
} }
@@ -5,16 +5,19 @@
package org.jetbrains.kotlin.analysis.api.calls 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.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol 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 import org.jetbrains.kotlin.psi.KtExpression
/** /**
* Represents direct or indirect (via invoke) function call from Kotlin code * 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 isErrorCall: Boolean
public abstract val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol> public abstract val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>
public abstract val targetFunction: KtCallTarget public abstract val targetFunction: KtCallTarget
@@ -28,11 +31,17 @@ public sealed class KtCall {
* } * }
*/ */
public class KtFunctionalTypeVariableCall( public class KtFunctionalTypeVariableCall(
public val target: KtVariableLikeSymbol, private val _target: KtVariableLikeSymbol,
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>, private val _argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>,
override val targetFunction: KtCallTarget private val _targetFunction: KtCallTarget,
override val token: ValidityToken
) : KtCall() { ) : 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<KtExpression, KtValueParameterSymbol>
get() = withValidityAssertion { _argumentMapping }
override val targetFunction: KtCallTarget
get() = withValidityAssertion { _targetFunction }
} }
/** /**
@@ -40,7 +49,7 @@ public class KtFunctionalTypeVariableCall(
*/ */
public sealed class KtDeclaredFunctionCall : KtCall() { public sealed class KtDeclaredFunctionCall : KtCall() {
override val isErrorCall: Boolean 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 class KtVariableWithInvokeFunctionCall(
public val target: KtVariableLikeSymbol, public val target: KtVariableLikeSymbol,
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>, private val _argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>,
private val _targetFunction: KtCallTarget,
override val token: ValidityToken
) : KtDeclaredFunctionCall() {
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>
get() = withValidityAssertion { _argumentMapping }
override val targetFunction: KtCallTarget override val targetFunction: KtCallTarget
) : KtDeclaredFunctionCall() get() = withValidityAssertion { _targetFunction }
}
/** /**
* Simple function call, e.g., * Simple function call, e.g.,
@@ -64,9 +79,15 @@ public class KtVariableWithInvokeFunctionCall(
* x.toString() // function call * x.toString() // function call
*/ */
public class KtFunctionCall( public class KtFunctionCall(
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>, private val _argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>,
private val _targetFunction: KtCallTarget,
override val token: ValidityToken
) : KtDeclaredFunctionCall() {
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>
get() = withValidityAssertion { _argumentMapping }
override val targetFunction: KtCallTarget override val targetFunction: KtCallTarget
) : KtDeclaredFunctionCall() get() = withValidityAssertion { _targetFunction }
}
/** /**
* Annotation call, e.g., * Annotation call, e.g.,
@@ -75,9 +96,15 @@ public class KtFunctionCall(
* annotation class Ann * annotation class Ann
*/ */
public class KtAnnotationCall( public class KtAnnotationCall(
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>, private val _argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>,
private val _targetFunction: KtCallTarget,
override val token: ValidityToken
) : KtDeclaredFunctionCall() {
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>
get() = withValidityAssertion { _argumentMapping }
override val targetFunction: KtCallTarget override val targetFunction: KtCallTarget
) : KtDeclaredFunctionCall() get() = withValidityAssertion { _targetFunction }
}
// TODO: Add other properties, e.g., useSiteTarget // TODO: Add other properties, e.g., useSiteTarget
/** /**
@@ -89,10 +116,16 @@ public class KtAnnotationCall(
* } * }
*/ */
public class KtDelegatedConstructorCall( public class KtDelegatedConstructorCall(
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>, private val _argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>,
override val targetFunction: KtCallTarget, private val _targetFunction: KtCallTarget,
public val kind: KtDelegatedConstructorCallKind public val kind: KtDelegatedConstructorCallKind,
) : KtDeclaredFunctionCall() override val token: ValidityToken
) : KtDeclaredFunctionCall() {
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>
get() = withValidityAssertion { _argumentMapping }
override val targetFunction: KtCallTarget
get() = withValidityAssertion { _targetFunction }
}
public enum class KtDelegatedConstructorCallKind { SUPER_CALL, THIS_CALL } 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 * 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 * 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<KtFunctionLikeSymbol> public abstract val candidates: Collection<KtFunctionLikeSymbol>
} }
/** /**
* Success call of [symbol] * Success call of [symbol]
*/ */
public class KtSuccessCallTarget(public val symbol: KtFunctionLikeSymbol) : KtCallTarget() { public class KtSuccessCallTarget(private val _symbol: KtFunctionLikeSymbol, override val token: ValidityToken) : KtCallTarget() {
override val candidates: Collection<KtFunctionLikeSymbol> public val symbol: KtFunctionLikeSymbol get() = withValidityAssertion { _symbol }
get() = listOf(symbol) override val candidates: Collection<KtFunctionLikeSymbol> get() = withValidityAssertion { listOf(symbol) }
} }
/** /**
* Function all with errors, possible candidates are [candidates] * Function call with errors, possible candidates are [candidates]
*/ */
public class KtErrorCallTarget( public class KtErrorCallTarget(
override val candidates: Collection<KtFunctionLikeSymbol>, private val _candidates: Collection<KtFunctionLikeSymbol>,
public val diagnostic: KtDiagnostic private val _diagnostic: KtDiagnostic,
) : KtCallTarget() override val token: ValidityToken
) : KtCallTarget() {
public val diagnostic: KtDiagnostic get() = withValidityAssertion { _diagnostic }
override val candidates: Collection<KtFunctionLikeSymbol> get() = withValidityAssertion { _candidates }
}