From d716c68f0efeedd51650801c309c6cab0fc7a366 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 15 Jun 2022 17:27:57 +0200 Subject: [PATCH] [Analysis API] cleanup code --- .../analysis/api/fir/KtSymbolByFirBuilder.kt | 6 +-- .../api/fir/scopes/KtFirDelegatingScope.kt | 2 +- .../AbstractKtSignatureSubstitutorImpl.kt | 21 ----------- .../AbstractSubstitutorBuilderTest.kt | 3 +- .../api/components/KtSignatureSubstitutor.kt | 37 +++++++++++++++---- .../services/KtSymbolByNameProvider.kt | 9 ++++- .../framework/services/SubstitutionParser.kt | 14 ++----- .../test/framework/services/TypeParser.kt | 22 ++++++----- 8 files changed, 58 insertions(+), 56 deletions(-) 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 3383caae645..c2e39193cf1 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 @@ -589,10 +589,8 @@ internal class KtSymbolByFirBuilder constructor( } -private class BuilderCache private constructor( - private val cache: ConcurrentMap, -) { - constructor() : this(ContainerUtil.createConcurrentSoftMap()) +private class BuilderCache { + private val cache = ContainerUtil.createConcurrentSoftMap() inline fun cache(key: From, calculation: () -> S): S { val value = cache.getOrPut(key, calculation) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatingScope.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatingScope.kt index f5076b0a7be..bd825747d4f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatingScope.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/scopes/KtFirDelegatingScope.kt @@ -27,7 +27,7 @@ internal open class KtFirDelegatingScope( getPossibleCallableNames() + getPossibleClassifierNames() } - override fun getAllPossibleNames(): Set = withValidityAssertion { withValidityAssertion { allNamesCached } } + override fun getAllPossibleNames(): Set = withValidityAssertion { allNamesCached } override fun getPossibleCallableNames(): Set = withValidityAssertion { firScope.getCallableNames() 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 126f7b4feb3..ad75a38b75c 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 @@ -14,17 +14,6 @@ import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() { - @Suppress("UNCHECKED_CAST") - override 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 - } - } - } override fun substitute( signature: KtVariableLikeSignature, @@ -51,16 +40,6 @@ abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() { ) } - - @Suppress("UNCHECKED_CAST") - override fun substitute(symbol: S, substitutor: KtSubstitutor): KtCallableSignature { - return when (symbol) { - is KtFunctionLikeSymbol -> substitute(symbol, substitutor) - is KtVariableLikeSymbol -> substitute(symbol, substitutor) - else -> unexpectedElementError("symbol", symbol) - } - } - override fun substitute(symbol: S, substitutor: KtSubstitutor): KtFunctionLikeSignature { if (substitutor is KtSubstitutor.Empty) return asSignature(symbol) return KtFunctionLikeSignature( diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/substututorFactory/AbstractSubstitutorBuilderTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/substututorFactory/AbstractSubstitutorBuilderTest.kt index eb61cd857ce..f8276e2f027 100644 --- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/substututorFactory/AbstractSubstitutorBuilderTest.kt +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/substututorFactory/AbstractSubstitutorBuilderTest.kt @@ -7,14 +7,13 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.substu import org.jetbrains.kotlin.analysis.api.components.buildClassType import org.jetbrains.kotlin.analysis.api.components.buildSubstitutor -import org.jetbrains.kotlin.analysis.api.components.buildTypeParameterType -import org.jetbrains.kotlin.analysis.api.impl.base.KtMapBackedSubstitutor import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.stringRepresentation import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.getSymbolOfType import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSingleFileTest import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider import org.jetbrains.kotlin.analysis.test.framework.services.getSymbolByName +import org.jetbrains.kotlin.analysis.test.framework.services.getSymbolByNameSafe import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.psi.KtDeclaration 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 f84d1e963dc..80a45dc2ee2 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 @@ -9,14 +9,27 @@ import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion 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.* +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 public abstract class KtSignatureSubstitutor : KtAnalysisSessionComponent() { - public abstract fun substitute( + @Suppress("UNCHECKED_CAST") + public open fun substitute( signature: KtCallableSignature, substitutor: KtSubstitutor - ): KtCallableSignature + ): 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, @@ -28,17 +41,27 @@ public abstract class KtSignatureSubstitutor : KtAnalysisSessionComponent() { substitutor: KtSubstitutor ): KtVariableLikeSignature - public abstract fun substitute(symbol: S, substitutor: KtSubstitutor): KtCallableSignature + @Suppress("UNCHECKED_CAST") + public open fun substitute(symbol: S, substitutor: KtSubstitutor): KtCallableSignature { + return when (symbol) { + is KtFunctionLikeSymbol -> substitute(symbol, substitutor) + is KtVariableLikeSymbol -> substitute(symbol, substitutor) + else -> unexpectedElementError("symbol", symbol) + } + } public abstract fun substitute(symbol: S, substitutor: KtSubstitutor): KtFunctionLikeSignature public abstract fun substitute(symbol: S, substitutor: KtSubstitutor): KtVariableLikeSignature - public abstract fun asSignature(symbol: S): KtCallableSignature + public open fun asSignature(symbol: S): KtCallableSignature = + substitute(symbol, KtSubstitutor.Empty(token)) - public abstract fun asSignature(symbol: S): KtFunctionLikeSignature + public open fun asSignature(symbol: S): KtFunctionLikeSignature = + substitute(symbol, KtSubstitutor.Empty(token)) - public abstract fun asSignature(symbol: S): KtVariableLikeSignature + public open fun asSignature(symbol: S): KtVariableLikeSignature = + substitute(symbol, KtSubstitutor.Empty(token)) } public interface KtSignatureSubstitutorMixIn : KtAnalysisSessionMixIn { diff --git a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/KtSymbolByNameProvider.kt b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/KtSymbolByNameProvider.kt index b634508e4ed..2f4fbf8a318 100644 --- a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/KtSymbolByNameProvider.kt +++ b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/KtSymbolByNameProvider.kt @@ -11,9 +11,14 @@ import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType -inline fun KtAnalysisSession.getSymbolByName(scope: KtElement, name: String): S { +inline fun KtAnalysisSession.getSymbolByNameSafe(scope: KtElement, name: String): S? { return scope.collectDescendantsOfType { it.name == name } .map { it.getSymbol() } .filterIsInstance() - .single() + .singleOrNull() +} + +inline fun KtAnalysisSession.getSymbolByName(scope: KtElement, name: String): S { + return getSymbolByNameSafe(scope, name) + ?: error("Symbol with $name was not found in scope") } \ No newline at end of file diff --git a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/SubstitutionParser.kt b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/SubstitutionParser.kt index 998ae7e71f1..b64a32994f9 100644 --- a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/SubstitutionParser.kt +++ b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/SubstitutionParser.kt @@ -8,12 +8,11 @@ package org.jetbrains.kotlin.analysis.test.framework.services import com.intellij.psi.PsiComment import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.components.buildSubstitutor +import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType object SubstitutionParser { context(KtAnalysisSession) @@ -35,16 +34,11 @@ object SubstitutionParser { check(directivesAsString.startsWith(SUBSTITUTOR_PREFIX)) val substitutorAsMap = parseSubstitutions(directivesAsString.removePrefix(SUBSTITUTOR_PREFIX)) - val allTypeParameterSymbols = scopeForTypeParameters - .collectDescendantsOfType() - .map { it.getTypeParameterSymbol() } - .groupBy { it.name.asString() } - .mapValues { it.value.single() } - return buildSubstitutor { substitutorAsMap.forEach { (typeParameterName, typeString) -> - val typeParameterSymbol = allTypeParameterSymbols.getValue(typeParameterName) - val type = TypeParser.parseTypeFromString(typeString, scopeForTypeParameters, allTypeParameterSymbols) + val typeParameterSymbol = getSymbolByNameSafe(scopeForTypeParameters, typeParameterName) + ?: error("Type parameter with name $typeParameterName was not found") + val type = TypeParser.parseTypeFromString(typeString, scopeForTypeParameters, scopeForTypeParameters) substitution(typeParameterSymbol, type) } } diff --git a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/TypeParser.kt b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/TypeParser.kt index a72bded5783..2276e205f13 100644 --- a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/TypeParser.kt +++ b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/TypeParser.kt @@ -19,25 +19,29 @@ object TypeParser { fun parseTypeFromString( stringType: String, contextElement: KtElement, - typeParameterByName: Map + scopeForTypeParameters: KtElement, ): KtType { val type = KtPsiFactory(contextElement).createType(stringType) - return convertType(type.typeElement ?: incorrectType(type), typeParameterByName) + return convertType(type.typeElement ?: incorrectType(type), scopeForTypeParameters) } context (KtAnalysisSession) - private fun convertType(type: KtTypeElement, typeParameterByName: Map): KtType = + private fun convertType(type: KtTypeElement, scopeForTypeParameters: KtElement): KtType = when (type) { is KtUserType -> { val qualifier = fullQualifier(type) - if (qualifier in typeParameterByName) { - buildTypeParameterType(typeParameterByName.getValue(qualifier)) - } else { - buildClassType(ClassId.topLevel(FqName(qualifier))) { - type.typeArguments.forEach { argument -> - argument(convertType(argument.typeReference?.typeElement ?: incorrectType(type), typeParameterByName)) + when (val typeParameter = getSymbolByNameSafe(scopeForTypeParameters, qualifier)) { + null -> { + buildClassType(ClassId.topLevel(FqName(qualifier))) { + type.typeArguments.forEach { argument -> + argument(convertType(argument.typeReference?.typeElement ?: incorrectType(type), scopeForTypeParameters)) + } } } + else -> { + buildTypeParameterType(typeParameter) + + } } } else -> TODO(type::class.java.name)