From 2cc3b542fda823961e1e668ae6e06805c4f68f30 Mon Sep 17 00:00:00 2001 From: aleksandrina-streltsova Date: Thu, 13 Apr 2023 14:01:57 +0200 Subject: [PATCH] [Analysis API FIR] Initialize properties of `KtCallableSignature` lazily --- .../components/KtFe10CallResolver.kt | 10 +- .../components/KtFe10SignatureSubstitutor.kt | 19 +++- .../signatures/KtFe10FunctionLikeSignature.kt | 70 ++++++++++++ .../signatures/KtFe10VariableLikeSignature.kt | 56 +++++++++ .../analysis/api/fir/KtSymbolByFirBuilder.kt | 34 +++--- .../components/KtFirSignatureSubstitutor.kt | 23 +++- .../fir/signatures/FirSymbolBasedSignature.kt | 14 +++ .../signatures/KtFirFunctionLikeSignature.kt | 106 ++++++++++++++++++ .../signatures/KtFirVariableLikeSignature.kt | 99 ++++++++++++++++ .../signatures/SubstitutorBasedSignature.kt | 12 ++ .../AbstractKtSignatureSubstitutor.kt | 36 ++++++ .../AbstractKtSignatureSubstitutorImpl.kt | 80 ------------- .../base/test/cases/components/testUtils.kt | 27 ++++- .../api/components/KtSignatureSubstitutor.kt | 58 +--------- .../api/signatures/KtCallableSignature.kt | 8 ++ .../api/signatures/KtFunctionLikeSignature.kt | 46 +------- .../api/signatures/KtVariableLikeSignature.kt | 43 +------ 17 files changed, 496 insertions(+), 245 deletions(-) create mode 100644 analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/signatures/KtFe10FunctionLikeSignature.kt create mode 100644 analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/signatures/KtFe10VariableLikeSignature.kt create mode 100644 analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/FirSymbolBasedSignature.kt create mode 100644 analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/KtFirFunctionLikeSignature.kt create mode 100644 analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/KtFirVariableLikeSignature.kt create mode 100644 analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/SubstitutorBasedSignature.kt create mode 100644 analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/AbstractKtSignatureSubstitutor.kt delete mode 100644 analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/AbstractKtSignatureSubstitutorImpl.kt diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CallResolver.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CallResolver.kt index 01053b69abe..8812364385e 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CallResolver.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CallResolver.kt @@ -10,6 +10,8 @@ import org.jetbrains.kotlin.analysis.api.calls.* import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession import org.jetbrains.kotlin.analysis.api.descriptors.components.base.Fe10KtAnalysisSessionComponent +import org.jetbrains.kotlin.analysis.api.descriptors.signatures.KtFe10FunctionLikeSignature +import org.jetbrains.kotlin.analysis.api.descriptors.signatures.KtFe10VariableLikeSignature import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.KtFe10DescValueParameterSymbol import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.KtFe10ReceiverParameterSymbol import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.KtFe10DescSymbol @@ -59,10 +61,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.UnwrappedType -import org.jetbrains.kotlin.types.asSimpleType -import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.contains -import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.isTypeVariable -import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.typeConstructor import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.util.OperatorNameConventions @@ -567,8 +565,8 @@ internal class KtFe10CallResolver( resultingDescriptor.extensionReceiverParameter?.returnType?.toKtType(analysisContext) } return when (symbol) { - is KtVariableLikeSymbol -> KtVariableLikeSignature(symbol, ktReturnType, receiverType) - is KtFunctionLikeSymbol -> KtFunctionLikeSignature( + is KtVariableLikeSymbol -> KtFe10VariableLikeSignature(symbol, ktReturnType, receiverType) + is KtFunctionLikeSymbol -> KtFe10FunctionLikeSignature( symbol, ktReturnType, receiverType, diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SignatureSubstitutor.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SignatureSubstitutor.kt index 5aa29770071..c550c2cec57 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SignatureSubstitutor.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10SignatureSubstitutor.kt @@ -7,8 +7,23 @@ package org.jetbrains.kotlin.analysis.api.descriptors.components import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession import org.jetbrains.kotlin.analysis.api.descriptors.components.base.Fe10KtAnalysisSessionComponent -import org.jetbrains.kotlin.analysis.api.impl.base.components.AbstractKtSignatureSubstitutorImpl +import org.jetbrains.kotlin.analysis.api.descriptors.signatures.KtFe10FunctionLikeSignature +import org.jetbrains.kotlin.analysis.api.descriptors.signatures.KtFe10VariableLikeSignature +import org.jetbrains.kotlin.analysis.api.impl.base.components.AbstractKtSignatureSubstitutor +import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature +import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol +import org.jetbrains.kotlin.analysis.api.symbols.receiverType internal class KtFe10SignatureSubstitutor( override val analysisSession: KtFe10AnalysisSession -) : AbstractKtSignatureSubstitutorImpl(), Fe10KtAnalysisSessionComponent \ No newline at end of file +) : AbstractKtSignatureSubstitutor(), Fe10KtAnalysisSessionComponent { + override fun asSignature(symbol: S): KtFunctionLikeSignature { + return KtFe10FunctionLikeSignature(symbol, symbol.returnType, symbol.receiverType, symbol.valueParameters.map { asSignature(it) }) + } + + override fun asSignature(symbol: S): KtVariableLikeSignature { + return KtFe10VariableLikeSignature(symbol, symbol.returnType, symbol.receiverType) + } +} \ No newline at end of file diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/signatures/KtFe10FunctionLikeSignature.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/signatures/KtFe10FunctionLikeSignature.kt new file mode 100644 index 00000000000..5789ee709b9 --- /dev/null +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/signatures/KtFe10FunctionLikeSignature.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.descriptors.signatures + +import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature +import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor +import org.jetbrains.kotlin.analysis.api.types.KtType + +internal class KtFe10FunctionLikeSignature( + private val _symbol: S, + private val _returnType: KtType, + private val _receiverType: KtType?, + private val _valueParameters: List>, +) : KtFunctionLikeSignature() { + override val token: KtLifetimeToken + get() = _symbol.token + override val symbol: S + get() = withValidityAssertion { _symbol } + override val returnType: KtType + get() = withValidityAssertion { _returnType } + override val receiverType: KtType? + get() = withValidityAssertion { _receiverType } + override val valueParameters: List> + get() = withValidityAssertion { _valueParameters } + + override fun substitute(substitutor: KtSubstitutor): KtFunctionLikeSignature = withValidityAssertion { + KtFe10FunctionLikeSignature( + symbol, + substitutor.substitute(returnType), + receiverType?.let { substitutor.substitute(it) }, + valueParameters.map { valueParameter -> + KtFe10VariableLikeSignature( + valueParameter.symbol, + substitutor.substitute(valueParameter.returnType), + valueParameter.receiverType?.let { substitutor.substitute(it) } + ) + } + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as KtFunctionLikeSignature<*> + + if (symbol != other.symbol) return false + if (returnType != other.returnType) return false + if (receiverType != other.receiverType) return false + if (valueParameters != other.valueParameters) return false + + return true + } + + override fun hashCode(): Int { + var result = symbol.hashCode() + result = 31 * result + returnType.hashCode() + result = 31 * result + (receiverType?.hashCode() ?: 0) + result = 31 * result + valueParameters.hashCode() + return result + } +} diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/signatures/KtFe10VariableLikeSignature.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/signatures/KtFe10VariableLikeSignature.kt new file mode 100644 index 00000000000..4d615c8538a --- /dev/null +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/signatures/KtFe10VariableLikeSignature.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.descriptors.signatures + +import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature +import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor +import org.jetbrains.kotlin.analysis.api.types.KtType + +internal class KtFe10VariableLikeSignature( + private val _symbol: S, + private val _returnType: KtType, + private val _receiverType: KtType?, +) : KtVariableLikeSignature() { + override val token: KtLifetimeToken + get() = _symbol.token + override val symbol: S + get() = withValidityAssertion { _symbol } + override val returnType: KtType + get() = withValidityAssertion { _returnType } + override val receiverType: KtType? + get() = withValidityAssertion { _receiverType } + + override fun substitute(substitutor: KtSubstitutor): KtVariableLikeSignature = withValidityAssertion { + KtFe10VariableLikeSignature( + symbol, + substitutor.substitute(returnType), + receiverType?.let { substitutor.substitute(it) }, + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as KtVariableLikeSignature<*> + + if (symbol != other.symbol) return false + if (returnType != other.returnType) return false + if (receiverType != other.receiverType) return false + + return true + } + + override fun hashCode(): Int { + var result = symbol.hashCode() + result = 31 * result + returnType.hashCode() + result = 31 * result + (receiverType?.hashCode() ?: 0) + return result + } +} \ No newline at end of file diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt index 572c4c93c61..ea26b2d2420 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt @@ -62,6 +62,8 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.types.Variance import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract +import org.jetbrains.kotlin.analysis.api.fir.signatures.KtFirFunctionLikeSubstitutorBasedSignature +import org.jetbrains.kotlin.analysis.api.fir.signatures.KtFirVariableLikeSubstitutorBasedSignature /** * Maps FirElement to KtSymbol & ConeType to KtType, thread safe @@ -219,19 +221,7 @@ internal class KtSymbolByFirBuilder constructor( fun buildFunctionSignature(firSymbol: FirNamedFunctionSymbol): KtFunctionLikeSignature { firSymbol.lazyResolveToPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) - val functionSymbol = buildFunctionSymbol(firSymbol) - return KtFunctionLikeSignature( - functionSymbol, - typeBuilder.buildKtType(firSymbol.resolvedReturnType), - firSymbol.resolvedReceiverTypeRef?.let { typeBuilder.buildKtType(it) }, - functionSymbol.valueParameters.zip(firSymbol.fir.valueParameters).map { (ktSymbol, fir) -> - var type = fir.returnTypeRef.coneType - if (fir.isVararg) { - type = type.arrayElementType() ?: type - } - KtVariableLikeSignature(ktSymbol, typeBuilder.buildKtType(type), null) - } - ) + return KtFirFunctionLikeSubstitutorBasedSignature(analysisSession.token, firSymbol, analysisSession.firSymbolBuilder) } fun buildAnonymousFunctionSymbol(firSymbol: FirAnonymousFunctionSymbol): KtFirAnonymousFunctionSymbol { @@ -311,11 +301,7 @@ internal class KtSymbolByFirBuilder constructor( fun buildPropertySignature(firSymbol: FirPropertySymbol): KtVariableLikeSignature { firSymbol.lazyResolveToPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) - return KtVariableLikeSignature( - buildPropertySymbol(firSymbol), - typeBuilder.buildKtType(firSymbol.fir.returnTypeRef), - firSymbol.resolvedReceiverTypeRef?.let { typeBuilder.buildKtType(it) } - ) + return KtFirVariableLikeSubstitutorBasedSignature(analysisSession.token, firSymbol, analysisSession.firSymbolBuilder) } fun buildLocalVariableSymbol(firSymbol: FirPropertySymbol): KtFirLocalVariableSymbol { @@ -332,6 +318,9 @@ internal class KtSymbolByFirBuilder constructor( } fun buildValueParameterSymbol(firSymbol: FirValueParameterSymbol): KtValueParameterSymbol { + firSymbol.fir.unwrapSubstitutionOverrideIfNeeded()?.let { + return buildValueParameterSymbol(it.symbol) + } return symbolsCache.cache(firSymbol) { KtFirValueParameterSymbol(firSymbol, analysisSession) } @@ -529,8 +518,8 @@ internal class KtSymbolByFirBuilder constructor( private inline fun T.unwrapUseSiteSubstitutionOverride(): T? { val originalDeclaration = originalForSubstitutionOverride ?: return null - val containingClass = getContainingClass(rootSession) ?: return null - val originalContainingClass = originalDeclaration.getContainingClass(rootSession) ?: return null + val containingClass = getContainingMemberOrSelf().getContainingClass(rootSession) ?: return null + val originalContainingClass = originalDeclaration.getContainingMemberOrSelf().getContainingClass(rootSession) ?: return null // If substitution override does not change the containing class of the FIR declaration, // it is a use-site substitution override @@ -539,6 +528,11 @@ internal class KtSymbolByFirBuilder constructor( return originalDeclaration } + private fun FirCallableDeclaration.getContainingMemberOrSelf(): FirCallableDeclaration = when (this) { + is FirValueParameter -> containingFunctionSymbol.fir + else -> this + } + /** * We want to unwrap a SUBSTITUTION_OVERRIDE wrapper if it doesn't affect the declaration's signature in any way. If the signature * is somehow changed, then we want to keep the wrapper. diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSignatureSubstitutor.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSignatureSubstitutor.kt index 3615ea4ac08..8584e044e36 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSignatureSubstitutor.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirSignatureSubstitutor.kt @@ -6,8 +6,27 @@ package org.jetbrains.kotlin.analysis.api.fir.components import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession -import org.jetbrains.kotlin.analysis.api.impl.base.components.AbstractKtSignatureSubstitutorImpl +import org.jetbrains.kotlin.analysis.api.fir.signatures.KtFirFunctionLikeDummySignature +import org.jetbrains.kotlin.analysis.api.fir.signatures.KtFirVariableLikeDummySignature +import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol +import org.jetbrains.kotlin.analysis.api.impl.base.components.AbstractKtSignatureSubstitutor +import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature +import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol internal class KtFirSignatureSubstitutor( override val analysisSession: KtFirAnalysisSession -) : AbstractKtSignatureSubstitutorImpl(), KtFirAnalysisSessionComponent \ No newline at end of file +) : AbstractKtSignatureSubstitutor(), KtFirAnalysisSessionComponent { + override fun asSignature(symbol: S): KtFunctionLikeSignature { + val firSymbol = (symbol as KtFirSymbol<*>).firSymbol as FirFunctionSymbol<*> + return KtFirFunctionLikeDummySignature(analysisSession.token, firSymbol, analysisSession.firSymbolBuilder) + } + + override fun asSignature(symbol: S): KtVariableLikeSignature { + val firSymbol = (symbol as KtFirSymbol<*>).firSymbol as FirVariableSymbol<*> + return KtFirVariableLikeDummySignature(analysisSession.token, firSymbol, analysisSession.firSymbolBuilder) + } +} \ No newline at end of file diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/FirSymbolBasedSignature.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/FirSymbolBasedSignature.kt new file mode 100644 index 00000000000..96ecfc6c402 --- /dev/null +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/FirSymbolBasedSignature.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.fir.signatures + +import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol + +internal interface FirSymbolBasedSignature { + val firSymbol: FirCallableSymbol<*> + val firSymbolBuilder: KtSymbolByFirBuilder +} \ No newline at end of file diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/KtFirFunctionLikeSignature.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/KtFirFunctionLikeSignature.kt new file mode 100644 index 00000000000..097e0ed7bc7 --- /dev/null +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/KtFirFunctionLikeSignature.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.fir.signatures + +import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.analysis.api.fir.buildSymbol +import org.jetbrains.kotlin.analysis.api.fir.types.AbstractKtFirSubstitutor +import org.jetbrains.kotlin.analysis.api.fir.utils.cached +import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature +import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature +import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol +import org.jetbrains.kotlin.analysis.api.symbols.receiverType +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor +import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor +import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol + +internal sealed class KtFirFunctionLikeSignature : KtFunctionLikeSignature(), FirSymbolBasedSignature { + abstract override fun substitute(substitutor: KtSubstitutor): KtFirFunctionLikeSignature + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as KtFirFunctionLikeSignature<*> + return firSymbol == other.firSymbol + } + + override fun hashCode(): Int = firSymbol.hashCode() +} + +internal class KtFirFunctionLikeDummySignature( + override val token: KtLifetimeToken, + override val firSymbol: FirFunctionSymbol<*>, + override val firSymbolBuilder: KtSymbolByFirBuilder, +) : KtFirFunctionLikeSignature() { + @Suppress("UNCHECKED_CAST") + override val symbol: S + get() = withValidityAssertion { firSymbol.buildSymbol(firSymbolBuilder) as S } + override val returnType: KtType + get() = withValidityAssertion { symbol.returnType } + override val receiverType: KtType? + get() = withValidityAssertion { symbol.receiverType } + override val valueParameters: List> by cached { + firSymbol.valueParameterSymbols.map { KtFirVariableLikeDummySignature(token, it, firSymbolBuilder) } + } + + override fun substitute(substitutor: KtSubstitutor): KtFirFunctionLikeSignature = withValidityAssertion { + if (substitutor is KtSubstitutor.Empty) return@withValidityAssertion this + require(substitutor is AbstractKtFirSubstitutor<*>) + + KtFirFunctionLikeSubstitutorBasedSignature(token, firSymbol, firSymbolBuilder, substitutor.substitutor) + } +} + +internal class KtFirFunctionLikeSubstitutorBasedSignature( + override val token: KtLifetimeToken, + override val firSymbol: FirFunctionSymbol<*>, + override val firSymbolBuilder: KtSymbolByFirBuilder, + override val coneSubstitutor: ConeSubstitutor = ConeSubstitutor.Empty, +) : KtFirFunctionLikeSignature(), SubstitutorBasedSignature { + @Suppress("UNCHECKED_CAST") + override val symbol: S + get() = withValidityAssertion { firSymbol.buildSymbol(firSymbolBuilder) as S } + override val returnType: KtType by cached { + firSymbolBuilder.typeBuilder.buildKtType(coneSubstitutor.substituteOrSelf(firSymbol.resolvedReturnType)) + } + override val receiverType: KtType? by cached { + val receiverTypeRef = when (val fir = firSymbol.fir) { + is FirPropertyAccessor -> fir.propertySymbol.resolvedReceiverTypeRef + else -> firSymbol.resolvedReceiverTypeRef + } + receiverTypeRef?.let { firSymbolBuilder.typeBuilder.buildKtType(coneSubstitutor.substituteOrSelf(it.type)) } + } + override val valueParameters: List> by cached { + firSymbol.fir.valueParameters.map { firValueParameter -> + KtFirVariableLikeSubstitutorBasedSignature(token, firValueParameter.symbol, firSymbolBuilder, coneSubstitutor) + } + } + + override fun substitute(substitutor: KtSubstitutor): KtFirFunctionLikeSignature = withValidityAssertion { + if (substitutor is KtSubstitutor.Empty) return@withValidityAssertion this + require(substitutor is AbstractKtFirSubstitutor<*>) + val chainedSubstitutor = ChainedSubstitutor(coneSubstitutor, substitutor.substitutor) + + KtFirFunctionLikeSubstitutorBasedSignature(token, firSymbol, firSymbolBuilder, chainedSubstitutor) + } + + override fun equals(other: Any?): Boolean { + if (!super.equals(other)) return false + + other as KtFirFunctionLikeSubstitutorBasedSignature<*> + return coneSubstitutor == other.coneSubstitutor + } + + override fun hashCode(): Int = 31 * super.hashCode() + coneSubstitutor.hashCode() +} \ No newline at end of file diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/KtFirVariableLikeSignature.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/KtFirVariableLikeSignature.kt new file mode 100644 index 00000000000..9d1a2253609 --- /dev/null +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/KtFirVariableLikeSignature.kt @@ -0,0 +1,99 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.fir.signatures + +import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.analysis.api.fir.buildSymbol +import org.jetbrains.kotlin.analysis.api.fir.types.AbstractKtFirSubstitutor +import org.jetbrains.kotlin.analysis.api.fir.utils.cached +import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken +import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion +import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature +import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol +import org.jetbrains.kotlin.analysis.api.symbols.receiverType +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor +import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol +import org.jetbrains.kotlin.fir.types.arrayElementType +import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.utils.addToStdlib.applyIf + +internal sealed class KtFirVariableLikeSignature : KtVariableLikeSignature(), FirSymbolBasedSignature { + abstract override fun substitute(substitutor: KtSubstitutor): KtFirVariableLikeSignature + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as KtFirVariableLikeSignature<*> + return firSymbol == other.firSymbol + } + + override fun hashCode(): Int = firSymbol.hashCode() +} + +internal class KtFirVariableLikeDummySignature( + override val token: KtLifetimeToken, + override val firSymbol: FirVariableSymbol<*>, + override val firSymbolBuilder: KtSymbolByFirBuilder, +) : KtFirVariableLikeSignature() { + @Suppress("UNCHECKED_CAST") + override val symbol: S + get() = withValidityAssertion { firSymbol.buildSymbol(firSymbolBuilder) as S } + override val returnType: KtType + get() = withValidityAssertion { symbol.returnType } + override val receiverType: KtType? + get() = withValidityAssertion { symbol.receiverType } + + override fun substitute(substitutor: KtSubstitutor): KtFirVariableLikeSignature = withValidityAssertion { + if (substitutor is KtSubstitutor.Empty) return@withValidityAssertion this + require(substitutor is AbstractKtFirSubstitutor<*>) + + KtFirVariableLikeSubstitutorBasedSignature(token, firSymbol, firSymbolBuilder, substitutor.substitutor) + } +} + +internal class KtFirVariableLikeSubstitutorBasedSignature( + override val token: KtLifetimeToken, + override val firSymbol: FirVariableSymbol<*>, + override val firSymbolBuilder: KtSymbolByFirBuilder, + override val coneSubstitutor: ConeSubstitutor = ConeSubstitutor.Empty, +) : KtFirVariableLikeSignature(), SubstitutorBasedSignature { + @Suppress("UNCHECKED_CAST") + override val symbol: S + get() = withValidityAssertion { firSymbol.buildSymbol(firSymbolBuilder) as S } + override val returnType: KtType by cached { + val isVarargValueParameter = (firSymbol as? FirValueParameterSymbol)?.isVararg == true + val coneType = firSymbol.resolvedReturnType.applyIf(isVarargValueParameter) { arrayElementType() ?: this } + + firSymbolBuilder.typeBuilder.buildKtType(coneSubstitutor.substituteOrSelf(coneType)) + } + override val receiverType: KtType? by cached { + firSymbol.resolvedReceiverTypeRef?.let { typeRef -> + firSymbolBuilder.typeBuilder.buildKtType(coneSubstitutor.substituteOrSelf(typeRef.coneType)) + } + } + + override fun substitute(substitutor: KtSubstitutor): KtFirVariableLikeSignature = withValidityAssertion { + if (substitutor is KtSubstitutor.Empty) return@withValidityAssertion this + require(substitutor is AbstractKtFirSubstitutor<*>) + val chainedSubstitutor = ChainedSubstitutor(coneSubstitutor, substitutor.substitutor) + + KtFirVariableLikeSubstitutorBasedSignature(token, firSymbol, firSymbolBuilder, chainedSubstitutor) + } + + override fun equals(other: Any?): Boolean { + if (!super.equals(other)) return false + + other as KtFirVariableLikeSubstitutorBasedSignature<*> + return coneSubstitutor == other.coneSubstitutor + } + + override fun hashCode(): Int = 31 * super.hashCode() + coneSubstitutor.hashCode() +} \ No newline at end of file diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/SubstitutorBasedSignature.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/SubstitutorBasedSignature.kt new file mode 100644 index 00000000000..f10c6513569 --- /dev/null +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/signatures/SubstitutorBasedSignature.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.fir.signatures + +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor + +internal interface SubstitutorBasedSignature { + val coneSubstitutor: ConeSubstitutor +} \ No newline at end of file diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/AbstractKtSignatureSubstitutor.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/AbstractKtSignatureSubstitutor.kt new file mode 100644 index 00000000000..265719a9f67 --- /dev/null +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/AbstractKtSignatureSubstitutor.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.impl.base.components + +import org.jetbrains.kotlin.analysis.api.components.KtSignatureSubstitutor +import org.jetbrains.kotlin.analysis.api.signatures.KtCallableSignature +import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature +import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature +import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor +import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError + +abstract class AbstractKtSignatureSubstitutor : KtSignatureSubstitutor() { + override fun substitute(symbol: S, substitutor: KtSubstitutor): KtFunctionLikeSignature { + if (substitutor is KtSubstitutor.Empty) return asSignature(symbol) + return asSignature(symbol).substitute(substitutor) + } + + override fun substitute(symbol: S, substitutor: KtSubstitutor): KtVariableLikeSignature { + if (substitutor is KtSubstitutor.Empty) return asSignature(symbol) + return asSignature(symbol).substitute(substitutor) + } + + override fun asSignature(symbol: S): KtCallableSignature { + return when (symbol) { + is KtFunctionLikeSymbol -> asSignature(symbol) + is KtVariableLikeSymbol -> asSignature(symbol) + else -> unexpectedElementError("symbol", symbol) + } + } +} \ No newline at end of file diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/AbstractKtSignatureSubstitutorImpl.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/AbstractKtSignatureSubstitutorImpl.kt deleted file mode 100644 index 9a9cbeb53d1..00000000000 --- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/AbstractKtSignatureSubstitutorImpl.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.analysis.api.impl.base.components - -import org.jetbrains.kotlin.analysis.api.components.KtSignatureSubstitutor -import org.jetbrains.kotlin.analysis.api.signatures.KtCallableSignature -import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature -import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature -import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.receiverType -import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor -import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError - -abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() { - - override fun substitute( - signature: KtVariableLikeSignature, - substitutor: KtSubstitutor - ): KtVariableLikeSignature { - if (substitutor is KtSubstitutor.Empty) return signature - return KtVariableLikeSignature( - signature.symbol, - substitutor.substitute(signature.returnType), - signature.receiverType?.let { substitutor.substitute(it) }, - ) - } - - override fun substitute( - signature: KtFunctionLikeSignature, - substitutor: KtSubstitutor - ): KtFunctionLikeSignature { - if (substitutor is KtSubstitutor.Empty) return signature - return KtFunctionLikeSignature( - signature.symbol, - substitutor.substitute(signature.returnType), - signature.receiverType?.let { substitutor.substitute(it) }, - signature.valueParameters.map { substitute(it, substitutor) } - ) - } - - override fun substitute(symbol: S, substitutor: KtSubstitutor): KtFunctionLikeSignature { - if (substitutor is KtSubstitutor.Empty) return asSignature(symbol) - return KtFunctionLikeSignature( - symbol, - substitutor.substitute(symbol.returnType), - symbol.receiverType?.let { substitutor.substitute(it) }, - symbol.valueParameters.map { substitute(it, substitutor) } - ) - } - - override fun substitute(symbol: S, substitutor: KtSubstitutor): KtVariableLikeSignature { - if (substitutor is KtSubstitutor.Empty) return asSignature(symbol) - return KtVariableLikeSignature( - symbol, - substitutor.substitute(symbol.returnType), - symbol.receiverType?.let { substitutor.substitute(it) }, - ) - } - - override fun asSignature(symbol: S): KtCallableSignature { - return when (symbol) { - is KtFunctionLikeSymbol -> asSignature(symbol) - is KtVariableLikeSymbol -> asSignature(symbol) - else -> unexpectedElementError("symbol", symbol) - } - } - - override fun asSignature(symbol: S): KtFunctionLikeSignature { - return KtFunctionLikeSignature(symbol, symbol.returnType, symbol.receiverType, symbol.valueParameters.map { asSignature(it) }) - } - - override fun asSignature(symbol: S): KtVariableLikeSignature { - return KtVariableLikeSignature(symbol, symbol.returnType, symbol.receiverType) - } -} \ No newline at end of file diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/testUtils.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/testUtils.kt index bf40e44649d..3750aada6c1 100644 --- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/testUtils.kt +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/testUtils.kt @@ -33,7 +33,6 @@ import kotlin.reflect.full.memberProperties @OptIn(KtAnalysisApiInternals::class) internal fun KtAnalysisSession.stringRepresentation(any: Any): String = with(any) { fun KtType.render() = asStringForDebugging().replace('/', '.') - fun String.indented() = replace("\n", "\n ") return when (this) { is KtFunctionLikeSymbol -> buildString { append( @@ -91,6 +90,7 @@ internal fun KtAnalysisSession.stringRepresentation(any: Any): String = with(any is Enum<*> -> name is Name -> asString() is CallableId -> toString() + is KtCallableSignature<*> -> this.stringRepresentation() else -> buildString { val clazz = this@with::class val className = clazz.simpleName!! @@ -114,6 +114,31 @@ internal fun KtAnalysisSession.stringRepresentation(any: Any): String = with(any } } +context(KtAnalysisSession) +private fun KtCallableSignature<*>.stringRepresentation(): String = buildString { + when (this@stringRepresentation) { + is KtFunctionLikeSignature<*> -> append(KtFunctionLikeSignature::class.simpleName) + is KtVariableLikeSignature<*> -> append(KtVariableLikeSignature::class.simpleName) + } + appendLine(":") + val memberProperties = listOfNotNull( + KtVariableLikeSignature<*>::name.takeIf { this@stringRepresentation is KtVariableLikeSignature<*> }, + KtCallableSignature<*>::receiverType, + KtCallableSignature<*>::returnType, + KtCallableSignature<*>::symbol, + KtFunctionLikeSignature<*>::valueParameters.takeIf { this@stringRepresentation is KtFunctionLikeSignature<*> }, + KtCallableSignature<*>::callableIdIfNonLocal + ) + memberProperties.joinTo(this, separator = "\n ", prefix = " ") { property -> + @Suppress("UNCHECKED_CAST") + val value = (property as KProperty1).get(this@stringRepresentation) + val valueAsString = value?.let { stringRepresentation(it).indented() } + "${property.name} = $valueAsString" + } +} + +private fun String.indented() = replace("\n", "\n ") + internal fun KtAnalysisSession.prettyPrintSignature(signature: KtCallableSignature<*>): String = prettyPrint { when (signature) { is KtFunctionLikeSignature -> { diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSignatureSubstitutor.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSignatureSubstitutor.kt index 565159700e9..36cca81c9f3 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSignatureSubstitutor.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSignatureSubstitutor.kt @@ -16,31 +16,6 @@ import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError public abstract class KtSignatureSubstitutor : KtAnalysisSessionComponent() { - @Suppress("UNCHECKED_CAST") - public open fun substitute( - signature: KtCallableSignature, - substitutor: KtSubstitutor - ): KtCallableSignature { - return when (signature) { - is KtFunctionLikeSignature -> { - substitute(signature as KtFunctionLikeSignature, substitutor) as KtCallableSignature - } - is KtVariableLikeSignature -> { - substitute(signature as KtVariableLikeSignature, substitutor) as KtCallableSignature - } - } - } - - public abstract fun substitute( - signature: KtFunctionLikeSignature, - substitutor: KtSubstitutor - ): KtFunctionLikeSignature - - public abstract fun substitute( - signature: KtVariableLikeSignature, - substitutor: KtSubstitutor - ): KtVariableLikeSignature - public open fun substitute(symbol: S, substitutor: KtSubstitutor): KtCallableSignature = when (symbol) { is KtFunctionLikeSymbol -> substitute(symbol, substitutor) is KtVariableLikeSymbol -> substitute(symbol, substitutor) @@ -51,41 +26,14 @@ public abstract class KtSignatureSubstitutor : KtAnalysisSessionComponent() { public abstract fun substitute(symbol: S, substitutor: KtSubstitutor): KtVariableLikeSignature - public open fun asSignature(symbol: S): KtCallableSignature = - substitute(symbol, KtSubstitutor.Empty(token)) + public abstract fun asSignature(symbol: S): KtCallableSignature - public open fun asSignature(symbol: S): KtFunctionLikeSignature = - substitute(symbol, KtSubstitutor.Empty(token)) + public abstract fun asSignature(symbol: S): KtFunctionLikeSignature - public open fun asSignature(symbol: S): KtVariableLikeSignature = - substitute(symbol, KtSubstitutor.Empty(token)) + public abstract fun asSignature(symbol: S): KtVariableLikeSignature } public interface KtSignatureSubstitutorMixIn : KtAnalysisSessionMixIn { - /** - * Applies a [substitutor] to the given signature and return a new signature with substituted types. - * - * @see KtSubstitutor.substitute - */ - public fun KtCallableSignature.substitute(substitutor: KtSubstitutor): KtCallableSignature = - withValidityAssertion { analysisSession.signatureSubstitutor.substitute(this, substitutor) } - - /** - * Applies a [substitutor] to the given signature and return a new signature with substituted types. - * - * @see KtSubstitutor.substitute - */ - public fun KtFunctionLikeSignature.substitute(substitutor: KtSubstitutor): KtFunctionLikeSignature = - withValidityAssertion { analysisSession.signatureSubstitutor.substitute(this, substitutor) } - - /** - * Applies a [substitutor] to the given signature and return a new signature with substituted types. - * - * @see KtSubstitutor.substitute - */ - public fun KtVariableLikeSignature.substitute(substitutor: KtSubstitutor): KtVariableLikeSignature = - withValidityAssertion { analysisSession.signatureSubstitutor.substitute(this, substitutor) } - /** * Applies a [substitutor] to the given symbol and return a signature with substituted types. * diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtCallableSignature.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtCallableSignature.kt index 52f3b34d974..a5c8b98a7dc 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtCallableSignature.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtCallableSignature.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.signatures import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.name.CallableId @@ -43,6 +44,13 @@ public sealed class KtCallableSignature : KtLifetimeOw */ public open val callableIdIfNonLocal: CallableId? get() = withValidityAssertion { symbol.callableIdIfNonLocal } + /** + * Applies a [substitutor] to the given signature and return a new signature with substituted types. + * + * @see KtSubstitutor.substitute + */ + public abstract fun substitute(substitutor: KtSubstitutor): KtCallableSignature + abstract override fun equals(other: Any?): Boolean abstract override fun hashCode(): Int } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtFunctionLikeSignature.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtFunctionLikeSignature.kt index 05766527fb5..83b334a4e51 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtFunctionLikeSignature.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtFunctionLikeSignature.kt @@ -5,57 +5,19 @@ package org.jetbrains.kotlin.analysis.api.signatures - -import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken -import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol -import org.jetbrains.kotlin.analysis.api.types.KtType +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor /** * A signature of a function-like symbol. This includes functions, getters, setters, lambdas, etc. */ -public class KtFunctionLikeSignature( - private val _symbol: S, - private val _returnType: KtType, - private val _receiverType: KtType?, - private val _valueParameters: List>, -) : KtCallableSignature() { - override val token: KtLifetimeToken - get() = _symbol.token - override val symbol: S - get() = withValidityAssertion { _symbol } - override val returnType: KtType - get() = withValidityAssertion { _returnType } - override val receiverType: KtType? - get() = withValidityAssertion { _receiverType } - +public abstract class KtFunctionLikeSignature : KtCallableSignature() { /** * The use-site-substituted value parameters. */ - public val valueParameters: List> - get() = withValidityAssertion { _valueParameters } + public abstract val valueParameters: List> - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as KtFunctionLikeSignature<*> - - if (_symbol != other._symbol) return false - if (_returnType != other._returnType) return false - if (_receiverType != other._receiverType) return false - if (_valueParameters != other._valueParameters) return false - - return true - } - - override fun hashCode(): Int { - var result = _symbol.hashCode() - result = 31 * result + _returnType.hashCode() - result = 31 * result + (_receiverType?.hashCode() ?: 0) - result = 31 * result + _valueParameters.hashCode() - return result - } + abstract override fun substitute(substitutor: KtSubstitutor): KtFunctionLikeSignature } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtVariableLikeSignature.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtVariableLikeSignature.kt index 1403f7fefe7..64a58687b88 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtVariableLikeSignature.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/signatures/KtVariableLikeSignature.kt @@ -8,9 +8,9 @@ package org.jetbrains.kotlin.analysis.api.signatures import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationWithArgumentsInfo import org.jetbrains.kotlin.analysis.api.annotations.KtConstantAnnotationValue import org.jetbrains.kotlin.analysis.api.annotations.annotationsByClassId -import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.api.symbols.KtVariableLikeSymbol +import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.name.Name @@ -21,20 +21,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf /** * A signature of a variable-like symbol. This includes properties, enum entries local variables, etc. */ -public class KtVariableLikeSignature( - private val _symbol: S, - private val _returnType: KtType, - private val _receiverType: KtType?, -) : KtCallableSignature() { - override val token: KtLifetimeToken - get() = _symbol.token - override val symbol: S - get() = withValidityAssertion { _symbol } - override val returnType: KtType - get() = withValidityAssertion { _returnType } - override val receiverType: KtType? - get() = withValidityAssertion { _receiverType } - +public abstract class KtVariableLikeSignature : KtCallableSignature() { /** * A name of the variable with respect to the `@ParameterName` annotation. Can be different from the [KtVariableLikeSymbol.name]. * @@ -66,11 +53,13 @@ public class KtVariableLikeSignature( // // fun foo(x: (item: Int) -> Unit) { x(1) } // fun bar(x: Function1<@ParameterName("item") Int, Unit>) { x(1) } - val nameCanBeDeclaredInAnnotation = _symbol.psi == null + val nameCanBeDeclaredInAnnotation = symbol.psi == null - runIf(nameCanBeDeclaredInAnnotation) { getValueFromParameterNameAnnotation() } ?: _symbol.name + runIf(nameCanBeDeclaredInAnnotation) { getValueFromParameterNameAnnotation() } ?: symbol.name } + abstract override fun substitute(substitutor: KtSubstitutor): KtVariableLikeSignature + private fun getValueFromParameterNameAnnotation(): Name? { val resultingAnnotation = findParameterNameAnnotation() ?: return null val parameterNameArgument = resultingAnnotation.arguments @@ -91,24 +80,4 @@ public class KtVariableLikeSignature( implicitAnnotations.singleOrNull() } } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as KtVariableLikeSignature<*> - - if (_symbol != other._symbol) return false - if (_returnType != other._returnType) return false - if (_receiverType != other._receiverType) return false - - return true - } - - override fun hashCode(): Int { - var result = _symbol.hashCode() - result = 31 * result + _returnType.hashCode() - result = 31 * result + (_receiverType?.hashCode() ?: 0) - return result - } }