[Analysis API] cleanup code

This commit is contained in:
Ilya Kirillov
2022-06-15 17:27:57 +02:00
parent 37b0c20879
commit d716c68f0e
8 changed files with 58 additions and 56 deletions
@@ -589,10 +589,8 @@ internal class KtSymbolByFirBuilder constructor(
} }
private class BuilderCache<From, To : Any> private constructor( private class BuilderCache<From, To : Any> {
private val cache: ConcurrentMap<From, To>, private val cache = ContainerUtil.createConcurrentSoftMap<From, To>()
) {
constructor() : this(ContainerUtil.createConcurrentSoftMap())
inline fun <reified S : To> cache(key: From, calculation: () -> S): S { inline fun <reified S : To> cache(key: From, calculation: () -> S): S {
val value = cache.getOrPut(key, calculation) val value = cache.getOrPut(key, calculation)
@@ -27,7 +27,7 @@ internal open class KtFirDelegatingScope(
getPossibleCallableNames() + getPossibleClassifierNames() getPossibleCallableNames() + getPossibleClassifierNames()
} }
override fun getAllPossibleNames(): Set<Name> = withValidityAssertion { withValidityAssertion { allNamesCached } } override fun getAllPossibleNames(): Set<Name> = withValidityAssertion { allNamesCached }
override fun getPossibleCallableNames(): Set<Name> = withValidityAssertion { override fun getPossibleCallableNames(): Set<Name> = withValidityAssertion {
firScope.getCallableNames() firScope.getCallableNames()
@@ -14,17 +14,6 @@ import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() { abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() {
@Suppress("UNCHECKED_CAST")
override fun <S : KtCallableSymbol> substitute(signature: KtCallableSignature<S>, substitutor: KtSubstitutor): KtCallableSignature<S> {
return when (signature) {
is KtFunctionLikeSignature -> {
substitute(signature as KtFunctionLikeSignature<KtFunctionLikeSymbol>, substitutor) as KtCallableSignature<S>
}
is KtVariableLikeSignature -> {
substitute(signature as KtVariableLikeSignature<KtVariableLikeSymbol>, substitutor) as KtCallableSignature<S>
}
}
}
override fun <S : KtVariableLikeSymbol> substitute( override fun <S : KtVariableLikeSymbol> substitute(
signature: KtVariableLikeSignature<S>, signature: KtVariableLikeSignature<S>,
@@ -51,16 +40,6 @@ abstract class AbstractKtSignatureSubstitutorImpl : KtSignatureSubstitutor() {
) )
} }
@Suppress("UNCHECKED_CAST")
override fun <S : KtCallableSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtCallableSignature<S> {
return when (symbol) {
is KtFunctionLikeSymbol -> substitute(symbol, substitutor)
is KtVariableLikeSymbol -> substitute(symbol, substitutor)
else -> unexpectedElementError("symbol", symbol)
}
}
override fun <S : KtFunctionLikeSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtFunctionLikeSignature<S> { override fun <S : KtFunctionLikeSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtFunctionLikeSignature<S> {
if (substitutor is KtSubstitutor.Empty) return asSignature(symbol) if (substitutor is KtSubstitutor.Empty) return asSignature(symbol)
return KtFunctionLikeSignature( return KtFunctionLikeSignature(
@@ -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.buildClassType
import org.jetbrains.kotlin.analysis.api.components.buildSubstitutor 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.impl.base.test.cases.components.stringRepresentation
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.getSymbolOfType import org.jetbrains.kotlin.analysis.api.symbols.getSymbolOfType
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiSingleFileTest 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.expressionMarkerProvider
import org.jetbrains.kotlin.analysis.test.framework.services.getSymbolByName 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.analysis.utils.printer.prettyPrint
import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
@@ -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.KtCallableSignature
import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature import org.jetbrains.kotlin.analysis.api.signatures.KtFunctionLikeSignature
import org.jetbrains.kotlin.analysis.api.signatures.KtVariableLikeSignature 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.api.types.KtSubstitutor
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
public abstract class KtSignatureSubstitutor : KtAnalysisSessionComponent() { public abstract class KtSignatureSubstitutor : KtAnalysisSessionComponent() {
public abstract fun <S : KtCallableSymbol> substitute( @Suppress("UNCHECKED_CAST")
public open fun <S : KtCallableSymbol> substitute(
signature: KtCallableSignature<S>, signature: KtCallableSignature<S>,
substitutor: KtSubstitutor substitutor: KtSubstitutor
): KtCallableSignature<S> ): KtCallableSignature<S> {
return when (signature) {
is KtFunctionLikeSignature -> {
substitute(signature as KtFunctionLikeSignature<KtFunctionLikeSymbol>, substitutor) as KtCallableSignature<S>
}
is KtVariableLikeSignature -> {
substitute(signature as KtVariableLikeSignature<KtVariableLikeSymbol>, substitutor) as KtCallableSignature<S>
}
}
}
public abstract fun <S : KtFunctionLikeSymbol> substitute( public abstract fun <S : KtFunctionLikeSymbol> substitute(
signature: KtFunctionLikeSignature<S>, signature: KtFunctionLikeSignature<S>,
@@ -28,17 +41,27 @@ public abstract class KtSignatureSubstitutor : KtAnalysisSessionComponent() {
substitutor: KtSubstitutor substitutor: KtSubstitutor
): KtVariableLikeSignature<S> ): KtVariableLikeSignature<S>
public abstract fun <S : KtCallableSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtCallableSignature<S> @Suppress("UNCHECKED_CAST")
public open fun <S : KtCallableSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtCallableSignature<S> {
return when (symbol) {
is KtFunctionLikeSymbol -> substitute(symbol, substitutor)
is KtVariableLikeSymbol -> substitute(symbol, substitutor)
else -> unexpectedElementError("symbol", symbol)
}
}
public abstract fun <S : KtFunctionLikeSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtFunctionLikeSignature<S> public abstract fun <S : KtFunctionLikeSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtFunctionLikeSignature<S>
public abstract fun <S : KtVariableLikeSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtVariableLikeSignature<S> public abstract fun <S : KtVariableLikeSymbol> substitute(symbol: S, substitutor: KtSubstitutor): KtVariableLikeSignature<S>
public abstract fun <S : KtCallableSymbol> asSignature(symbol: S): KtCallableSignature<S> public open fun <S : KtCallableSymbol> asSignature(symbol: S): KtCallableSignature<S> =
substitute(symbol, KtSubstitutor.Empty(token))
public abstract fun <S : KtFunctionLikeSymbol> asSignature(symbol: S): KtFunctionLikeSignature<S> public open fun <S : KtFunctionLikeSymbol> asSignature(symbol: S): KtFunctionLikeSignature<S> =
substitute(symbol, KtSubstitutor.Empty(token))
public abstract fun <S : KtVariableLikeSymbol> asSignature(symbol: S): KtVariableLikeSignature<S> public open fun <S : KtVariableLikeSymbol> asSignature(symbol: S): KtVariableLikeSignature<S> =
substitute(symbol, KtSubstitutor.Empty(token))
} }
public interface KtSignatureSubstitutorMixIn : KtAnalysisSessionMixIn { public interface KtSignatureSubstitutorMixIn : KtAnalysisSessionMixIn {
@@ -11,9 +11,14 @@ import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
inline fun <reified S : KtSymbol> KtAnalysisSession.getSymbolByName(scope: KtElement, name: String): S { inline fun <reified S : KtSymbol> KtAnalysisSession.getSymbolByNameSafe(scope: KtElement, name: String): S? {
return scope.collectDescendantsOfType<KtDeclaration> { it.name == name } return scope.collectDescendantsOfType<KtDeclaration> { it.name == name }
.map { it.getSymbol() } .map { it.getSymbol() }
.filterIsInstance<S>() .filterIsInstance<S>()
.single() .singleOrNull()
}
inline fun <reified S : KtSymbol> KtAnalysisSession.getSymbolByName(scope: KtElement, name: String): S {
return getSymbolByNameSafe(scope, name)
?: error("Symbol with $name was not found in scope")
} }
@@ -8,12 +8,11 @@ package org.jetbrains.kotlin.analysis.test.framework.services
import com.intellij.psi.PsiComment import com.intellij.psi.PsiComment
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.components.buildSubstitutor 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.analysis.api.types.KtSubstitutor
import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
object SubstitutionParser { object SubstitutionParser {
context(KtAnalysisSession) context(KtAnalysisSession)
@@ -35,16 +34,11 @@ object SubstitutionParser {
check(directivesAsString.startsWith(SUBSTITUTOR_PREFIX)) check(directivesAsString.startsWith(SUBSTITUTOR_PREFIX))
val substitutorAsMap = parseSubstitutions(directivesAsString.removePrefix(SUBSTITUTOR_PREFIX)) val substitutorAsMap = parseSubstitutions(directivesAsString.removePrefix(SUBSTITUTOR_PREFIX))
val allTypeParameterSymbols = scopeForTypeParameters
.collectDescendantsOfType<KtTypeParameter>()
.map { it.getTypeParameterSymbol() }
.groupBy { it.name.asString() }
.mapValues { it.value.single() }
return buildSubstitutor { return buildSubstitutor {
substitutorAsMap.forEach { (typeParameterName, typeString) -> substitutorAsMap.forEach { (typeParameterName, typeString) ->
val typeParameterSymbol = allTypeParameterSymbols.getValue(typeParameterName) val typeParameterSymbol = getSymbolByNameSafe<KtTypeParameterSymbol>(scopeForTypeParameters, typeParameterName)
val type = TypeParser.parseTypeFromString(typeString, scopeForTypeParameters, allTypeParameterSymbols) ?: error("Type parameter with name $typeParameterName was not found")
val type = TypeParser.parseTypeFromString(typeString, scopeForTypeParameters, scopeForTypeParameters)
substitution(typeParameterSymbol, type) substitution(typeParameterSymbol, type)
} }
} }
@@ -19,25 +19,29 @@ object TypeParser {
fun parseTypeFromString( fun parseTypeFromString(
stringType: String, stringType: String,
contextElement: KtElement, contextElement: KtElement,
typeParameterByName: Map<String, KtTypeParameterSymbol> scopeForTypeParameters: KtElement,
): KtType { ): KtType {
val type = KtPsiFactory(contextElement).createType(stringType) val type = KtPsiFactory(contextElement).createType(stringType)
return convertType(type.typeElement ?: incorrectType(type), typeParameterByName) return convertType(type.typeElement ?: incorrectType(type), scopeForTypeParameters)
} }
context (KtAnalysisSession) context (KtAnalysisSession)
private fun convertType(type: KtTypeElement, typeParameterByName: Map<String, KtTypeParameterSymbol>): KtType = private fun convertType(type: KtTypeElement, scopeForTypeParameters: KtElement): KtType =
when (type) { when (type) {
is KtUserType -> { is KtUserType -> {
val qualifier = fullQualifier(type) val qualifier = fullQualifier(type)
if (qualifier in typeParameterByName) { when (val typeParameter = getSymbolByNameSafe<KtTypeParameterSymbol>(scopeForTypeParameters, qualifier)) {
buildTypeParameterType(typeParameterByName.getValue(qualifier)) null -> {
} else { buildClassType(ClassId.topLevel(FqName(qualifier))) {
buildClassType(ClassId.topLevel(FqName(qualifier))) { type.typeArguments.forEach { argument ->
type.typeArguments.forEach { argument -> argument(convertType(argument.typeReference?.typeElement ?: incorrectType(type), scopeForTypeParameters))
argument(convertType(argument.typeReference?.typeElement ?: incorrectType(type), typeParameterByName)) }
} }
} }
else -> {
buildTypeParameterType(typeParameter)
}
} }
} }
else -> TODO(type::class.java.name) else -> TODO(type::class.java.name)