From f09459d172a429be25a4397cbf28aae2e40dadfd Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 9 Jun 2022 18:05:58 +0200 Subject: [PATCH] [Analysis API] add KDocs to the substitution-related functionality --- .../api/fir/types/KtFirSubstitutor.kt | 2 ++ .../api/impl/base/KtMapBackedSubstitutor.kt | 9 +++++ .../AbstractKtSignatureSubstitutorImpl.kt | 16 ++++----- ...stractAnalysisApiSignatureContractsTest.kt | 10 +++--- .../api/components/KtSignatureSubstitutor.kt | 20 +++++------ .../api/components/KtSubstitutorFactory.kt | 12 +++++++ .../api/signatures/KtCallableSignature.kt | 3 ++ .../api/signatures/KtFunctionLikeSignature.kt | 2 +- .../api/signatures/KtVariableLikeSignature.kt | 2 +- .../analysis/api/types/KtSubstitutor.kt | 33 +++++++++++++++++-- 10 files changed, 81 insertions(+), 28 deletions(-) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirSubstitutor.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirSubstitutor.kt index e4fcc5b59b5..1d66e830d46 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirSubstitutor.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/KtFirSubstitutor.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.analysis.api.fir.types +import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder import org.jetbrains.kotlin.analysis.api.fir.utils.weakRef import org.jetbrains.kotlin.analysis.api.impl.base.KtMapBackedSubstitutor @@ -36,6 +37,7 @@ internal class KtFirGenericSubstitutor( token: KtLifetimeToken ) : AbstractKtFirSubstitutor(_substitutor, builder, token) +@OptIn(KtAnalysisApiInternals::class) internal class KtFirMapBackedSubstitutor( _substitutor: ConeSubstitutorByMap, builder: KtSymbolByFirBuilder, diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/KtMapBackedSubstitutor.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/KtMapBackedSubstitutor.kt index 3fb5bd8cef6..15fc9b5b47f 100644 --- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/KtMapBackedSubstitutor.kt +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/KtMapBackedSubstitutor.kt @@ -5,10 +5,19 @@ package org.jetbrains.kotlin.analysis.api.impl.base +import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor import org.jetbrains.kotlin.analysis.api.types.KtType +/** + * A [KtSubstitutor] which substitution logic can be represented as a [Map] from a [KtTypeParameterSymbol] to corresponding [KtType] + * This is an implementation details and Analysis API clients should not depend on the fact if some [KtSubstitutor] is [KtMapBackedSubstitutor] or not. + */ +@KtAnalysisApiInternals interface KtMapBackedSubstitutor : KtSubstitutor { + /** + * Substitution rules in a form of a `Map` + */ fun getAsMap(): Map } \ 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 index b15a199706c..126f7b4feb3 100644 --- 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 @@ -33,8 +33,8 @@ abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() { if (substitutor is KtSubstitutor.Empty) return signature return KtVariableLikeSignature( signature.symbol, - substitutor.substituteOrSelf(signature.returnType), - signature.receiverType?.let { substitutor.substituteOrSelf(it) }, + substitutor.substitute(signature.returnType), + signature.receiverType?.let { substitutor.substitute(it) }, ) } @@ -45,8 +45,8 @@ abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() { if (substitutor is KtSubstitutor.Empty) return signature return KtFunctionLikeSignature( signature.symbol, - substitutor.substituteOrSelf(signature.returnType), - signature.receiverType?.let { substitutor.substituteOrSelf(it) }, + substitutor.substitute(signature.returnType), + signature.receiverType?.let { substitutor.substitute(it) }, signature.valueParameters.map { substitute(it, substitutor) } ) } @@ -65,8 +65,8 @@ abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() { if (substitutor is KtSubstitutor.Empty) return asSignature(symbol) return KtFunctionLikeSignature( symbol, - substitutor.substituteOrSelf(symbol.returnType), - symbol.receiverType?.let { substitutor.substituteOrSelf(it) }, + substitutor.substitute(symbol.returnType), + symbol.receiverType?.let { substitutor.substitute(it) }, symbol.valueParameters.map { substitute(it, substitutor) } ) } @@ -75,8 +75,8 @@ abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() { if (substitutor is KtSubstitutor.Empty) return asSignature(symbol) return KtVariableLikeSignature( symbol, - substitutor.substituteOrSelf(symbol.returnType), - symbol.receiverType?.let { substitutor.substituteOrSelf(it) }, + substitutor.substitute(symbol.returnType), + symbol.receiverType?.let { substitutor.substitute(it) }, ) } diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/signatureSubstitution/AbstractAnalysisApiSignatureContractsTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/signatureSubstitution/AbstractAnalysisApiSignatureContractsTest.kt index d9740c7953d..5cbc19fc5d7 100644 --- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/signatureSubstitution/AbstractAnalysisApiSignatureContractsTest.kt +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/signatureSubstitution/AbstractAnalysisApiSignatureContractsTest.kt @@ -102,13 +102,13 @@ abstract class AbstractAnalysisApiSignatureContractsTest : AbstractAnalysisApiSi substitutor: KtSubstitutor, testServices: TestServices ) { - testServices.assertions.assertEquals(symbol.receiverType?.let(substitutor::substituteOrSelf), signature.receiverType) - testServices.assertions.assertEquals(symbol.returnType.let(substitutor::substituteOrSelf), signature.returnType) + testServices.assertions.assertEquals(symbol.receiverType?.let(substitutor::substitute), signature.receiverType) + testServices.assertions.assertEquals(symbol.returnType.let(substitutor::substitute), signature.returnType) testServices.assertions.assertEquals(symbol.valueParameters.size, signature.valueParameters.size) for ((unsubstituted, substituted) in symbol.valueParameters.zip(signature.valueParameters)) { - testServices.assertions.assertEquals(substituted.returnType, unsubstituted.returnType.let(substitutor::substituteOrSelf)) + testServices.assertions.assertEquals(substituted.returnType, unsubstituted.returnType.let(substitutor::substitute)) } } @@ -118,8 +118,8 @@ abstract class AbstractAnalysisApiSignatureContractsTest : AbstractAnalysisApiSi substitutor: KtSubstitutor, testServices: TestServices ) { - testServices.assertions.assertEquals(symbol.receiverType?.let(substitutor::substituteOrSelf), signature.receiverType) - testServices.assertions.assertEquals(symbol.returnType.let(substitutor::substituteOrSelf), signature.returnType) + testServices.assertions.assertEquals(symbol.receiverType?.let(substitutor::substitute), signature.receiverType) + testServices.assertions.assertEquals(symbol.returnType.let(substitutor::substitute), signature.returnType) } private fun MutableList>.combinations(list: List, state: PersistentList, size: Int) { 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 e714ef0f13d..f84d1e963dc 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 @@ -45,39 +45,39 @@ public interface KtSignatureSubstitutorMixIn : KtAnalysisSessionMixIn { /** * Applies a [substitutor] to the given signature and return a new signature with substituted types. * - * @see KtSubstitutor.substituteOrSelf + * @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. + * Applies a [substitutor] to the given signature and return a new signature with substituted types. * - * @see KtSubstitutor.substituteOrSelf + * @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. + * Applies a [substitutor] to the given signature and return a new signature with substituted types. * - * @see KtSubstitutor.substituteOrSelf + * @see KtSubstitutor.substitute */ public fun KtVariableLikeSignature.substitute(substitutor: KtSubstitutor): KtVariableLikeSignature = withValidityAssertion { analysisSession.signatureSubstitutor.substitute(this, substitutor) } /** - * Applies a [substitutor] to the given symbols and return a signature with substituted types. + * Applies a [substitutor] to the given symbol and return a signature with substituted types. * - * @see KtSubstitutor.substituteOrSelf + * @see KtSubstitutor.substitute */ public fun S.substitute(substitutor: KtSubstitutor): KtCallableSignature = withValidityAssertion { analysisSession.signatureSubstitutor.substitute(this, substitutor) } /** - * Applies a [substitutor] to the given symbols and return a signature with substituted types. + * Applies a [substitutor] to the given symbol and return a signature with substituted types. * - * @see KtSubstitutor.substituteOrSelf + * @see KtSubstitutor.substitute */ public fun S.substitute(substitutor: KtSubstitutor): KtFunctionLikeSignature = withValidityAssertion { analysisSession.signatureSubstitutor.substitute(this, substitutor) } @@ -85,7 +85,7 @@ public interface KtSignatureSubstitutorMixIn : KtAnalysisSessionMixIn { /** * Applies a [substitutor] to the given symbols and return a signature with substituted types. * - * @see KtSubstitutor.substituteOrSelf + * @see KtSubstitutor.substitute */ public fun S.substitute(substitutor: KtSubstitutor): KtVariableLikeSignature = withValidityAssertion { analysisSession.signatureSubstitutor.substitute(this, substitutor) } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSubstitutorFactory.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSubstitutorFactory.kt index a10066938b0..2aa8f8db024 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSubstitutorFactory.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtSubstitutorFactory.kt @@ -22,6 +22,9 @@ public abstract class KtSubstitutorFactory : KtAnalysisSessionComponent() { public abstract fun buildSubstitutor(builder: KtSubstitutorBuilder): KtSubstitutor } +/** + * Creates new [KtSubstitutor] using substitutions specified inside [build] lambda + */ @OptIn(ExperimentalContracts::class, KtAnalysisApiInternals::class) public inline fun KtAnalysisSession.buildSubstitutor( build: KtSubstitutorBuilder.() -> Unit @@ -39,11 +42,20 @@ public class KtSubstitutorBuilder public val mappings: Map get() = withValidityAssertion { _mapping } + /** + * Adds a new [typeParameter] -> [type] substitution to the substitutor which is being built. + * If there already was a substitution with a [typeParameter], replaces corresponding substitution with a new one. + */ public fun substitution(typeParameter: KtTypeParameterSymbol, type: KtType) { assertIsValidAndAccessible() _mapping[typeParameter] = type } + /** + * Adds a new substitutions to the substitutor which is being built. + * If there already was a substitution with a [KtTypeParameterSymbol] which is present in a [substitutions], + * replaces corresponding substitution with a new one. + */ public fun substitutions(substitutions: Map) { assertIsValidAndAccessible() _mapping += substitutions 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 e8d95568f2d..52f3b34d974 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 @@ -38,6 +38,9 @@ public sealed class KtCallableSignature : KtLifetimeOw */ public abstract val receiverType: KtType? + /** + * A [CallableId] of a substituted symbol + */ public open val callableIdIfNonLocal: CallableId? get() = withValidityAssertion { symbol.callableIdIfNonLocal } abstract override fun equals(other: Any?): Boolean 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 e59ddd66ef3..05766527fb5 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 @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol import org.jetbrains.kotlin.analysis.api.types.KtType /** - * A signature of a function-like symbol. + * A signature of a function-like symbol. This includes functions, getters, setters, lambdas, etc. */ public class KtFunctionLikeSignature( private val _symbol: S, 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 94b16272cd5..c1611220949 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 @@ -19,7 +19,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf /** - * A signature of a variable-like symbol. + * A signature of a variable-like symbol. This includes properties, enum entries local variables, etc. */ public class KtVariableLikeSignature( private val _symbol: S, diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/types/KtSubstitutor.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/types/KtSubstitutor.kt index 46a91c856b2..e97f7b65da6 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/types/KtSubstitutor.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/types/KtSubstitutor.kt @@ -9,12 +9,39 @@ import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion - +/** + * Type substitutor. Performs substitution of a type parameters inside a type to some fixed type. + * Usually can be represented as a map from type parameter to it corresponding substitution. + * + * Example of a substitution: + * ``` + * substitutor = { T -> Int, S -> Long } + * substitute(Map, substitutor) = Map + * ``` + * + * Can be built by [org.jetbrains.kotlin.analysis.api.components.buildSubstitutor] or retrieved via a [org.jetbrains.kotlin.analysis.api.calls.KtCall] + */ public interface KtSubstitutor : KtLifetimeOwner { - public fun substituteOrSelf(type: KtType): KtType = withValidityAssertion { substituteOrNull(type) ?: type } + /** + * substitutes type parameters in a given type corresponding to internal mapping rules. + * + * @return substituted type if there was at least one substitution, [type] itself if there was no type parameter to substitute + */ + public fun substitute(type: KtType): KtType = withValidityAssertion { substituteOrNull(type) ?: type } + + /** + * substitutes type parameters in a given type corresponding to internal mapping rules. + * + * @return substituted type if there was at least one substitution, `null` if there was no type parameter to substitute + */ public fun substituteOrNull(type: KtType): KtType? + /** + * [KtSubstitutor] which does nothing on a type and always returns the type intact + */ public class Empty(override val token: KtLifetimeToken) : KtSubstitutor { - override fun substituteOrNull(type: KtType): KtType = withValidityAssertion { type } + override fun substituteOrNull(type: KtType): KtType? = withValidityAssertion { null } + + override fun substituteOrSelf(type: KtType): KtType = withValidityAssertion { type } } }