[AA] KT-56617 Introduce PSI-based Java type parameter symbols
- Instead of extending the API with `typeParameterNames`, this commit creates a PSI-based Java type parameter symbol similarly to the PSI-based Java class symbol. Because completion requires only the type parameter name, this approach works fine, and without exposing an optimization via the API.
This commit is contained in:
committed by
Space Team
parent
1e43e8d975
commit
037984b0e0
+14
-13
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||
import org.jetbrains.kotlin.analysis.utils.classIdIfNonLocal
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.java.classKind
|
||||
import org.jetbrains.kotlin.fir.java.modality
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
@@ -82,16 +83,21 @@ internal class KtFirPsiJavaClassSymbol(
|
||||
psi.containingClass?.let { KtFirPsiJavaClassSymbol(it, analysisSession) }
|
||||
}
|
||||
|
||||
override val typeParameterNames: List<Name> by cached {
|
||||
// The parent Java class might contribute `FirOuterClassTypeParameterRef`s to the FIR class's type parameters (see
|
||||
// `FirJavaFacade.createFirJavaClass`), but since they are filtered out by `createRegularKtTypeParameters`, we do not need to
|
||||
// include them in the list of type parameter names.
|
||||
javaClass.typeParameters.map { it.name }
|
||||
override val typeParameters: List<KtTypeParameterSymbol> by cached {
|
||||
// The parent Java class might contribute type parameters to the Java type parameter stack, but for this KtSymbol, parent type
|
||||
// parameters aren't relevant.
|
||||
psi.typeParameters.mapIndexed { index, psiTypeParameter ->
|
||||
KtFirPsiJavaTypeParameterSymbol(psiTypeParameter, analysisSession) {
|
||||
// `psi.typeParameters` should align with the list of regular `FirTypeParameter`s, making the use of `index` valid.
|
||||
val firTypeParameter = firSymbol.fir.typeParameters.filterIsInstance<FirTypeParameter>().getOrNull(index)
|
||||
require(firTypeParameter != null) {
|
||||
"The FIR symbol's ${FirTypeParameter::class.simpleName}s should have an entry at $index."
|
||||
}
|
||||
firTypeParameter.symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val hasTypeParameters: Boolean
|
||||
get() = withValidityAssertion { psi.typeParameters.isNotEmpty() }
|
||||
|
||||
val annotationSimpleNames: List<String?>
|
||||
get() = withValidityAssertion { psi.annotations.map { it.nameReferenceElement?.referenceName } }
|
||||
|
||||
@@ -122,11 +128,6 @@ internal class KtFirPsiJavaClassSymbol(
|
||||
firClassSymbol
|
||||
}
|
||||
|
||||
override val typeParameters: List<KtTypeParameterSymbol> by cached {
|
||||
if (hasTypeParameters) firSymbol.createRegularKtTypeParameters(builder)
|
||||
else emptyList()
|
||||
}
|
||||
|
||||
override val annotationsList: KtAnnotationsList by cached {
|
||||
if (hasAnnotations) KtFirAnnotationListForDeclaration.create(firSymbol, analysisSession.useSiteSession, token)
|
||||
else KtEmptyAnnotationsList(token)
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.symbols
|
||||
|
||||
import com.intellij.psi.PsiTypeParameter
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
/**
|
||||
* [KtFirPsiJavaTypeParameterSymbol] is a PSI-based type parameter symbol with a lazy [firSymbol]. Some properties such as [name] are
|
||||
* computed based on the PSI. This is used by [KtFirPsiJavaClassSymbol] to avoid building its own FIR symbol when a list of type parameters
|
||||
* is requested.
|
||||
*/
|
||||
internal class KtFirPsiJavaTypeParameterSymbol(
|
||||
override val psi: PsiTypeParameter,
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
private val computeFirSymbol: () -> FirTypeParameterSymbol,
|
||||
) : KtFirTypeParameterSymbolBase(), KtFirPsiSymbol<PsiTypeParameter, FirTypeParameterSymbol> {
|
||||
override val name: Name = withValidityAssertion {
|
||||
psi.name?.let { Name.identifier(it) } ?: SpecialNames.NO_NAME_PROVIDED
|
||||
}
|
||||
|
||||
override val origin: KtSymbolOrigin
|
||||
get() = withValidityAssertion { KtSymbolOrigin.JAVA }
|
||||
|
||||
override val variance: Variance
|
||||
get() = withValidityAssertion { Variance.INVARIANT }
|
||||
|
||||
override val isReified: Boolean
|
||||
get() = withValidityAssertion { false }
|
||||
|
||||
override val firSymbol: FirTypeParameterSymbol by cached {
|
||||
computeFirSymbol()
|
||||
}
|
||||
}
|
||||
+1
-42
@@ -6,65 +6,24 @@
|
||||
package org.jetbrains.kotlin.analysis.api.fir.symbols
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForDeclaration
|
||||
import org.jetbrains.kotlin.analysis.api.fir.findPsi
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.KtFirTypeParameterSymbolPointer
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.requireOwnerPointer
|
||||
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.symbols.KtTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
internal class KtFirTypeParameterSymbol(
|
||||
override val firSymbol: FirTypeParameterSymbol,
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
) : KtTypeParameterSymbol(), KtFirSymbol<FirTypeParameterSymbol> {
|
||||
) : KtFirTypeParameterSymbolBase() {
|
||||
override val token: KtLifetimeToken get() = builder.token
|
||||
override val psi: PsiElement? by cached { firSymbol.findPsi() }
|
||||
|
||||
override val annotationsList: KtAnnotationsList
|
||||
get() = withValidityAssertion {
|
||||
KtFirAnnotationListForDeclaration.create(firSymbol, analysisSession.useSiteSession, token)
|
||||
}
|
||||
|
||||
override val name: Name get() = withValidityAssertion { firSymbol.name }
|
||||
|
||||
override val upperBounds: List<KtType> by cached {
|
||||
firSymbol.resolvedBounds.mapNotNull { type ->
|
||||
if (type.isNullableAny) return@mapNotNull null
|
||||
builder.typeBuilder.buildKtType(type)
|
||||
}
|
||||
}
|
||||
|
||||
override val variance: Variance get() = withValidityAssertion { firSymbol.variance }
|
||||
override val isReified: Boolean get() = withValidityAssertion { firSymbol.isReified }
|
||||
|
||||
context(KtAnalysisSession)
|
||||
override fun createPointer(): KtSymbolPointer<KtTypeParameterSymbol> = withValidityAssertion {
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource<KtTypeParameterSymbol>(this)?.let { return it }
|
||||
|
||||
val containingDeclarationSymbol = firSymbol.containingDeclarationSymbol
|
||||
val typeParameters = containingDeclarationSymbol.typeParameterSymbols
|
||||
requireNotNull(typeParameters) { "Containing declaration symbol: ${containingDeclarationSymbol::class.simpleName}" }
|
||||
|
||||
KtFirTypeParameterSymbolPointer(
|
||||
ownerPointer = requireOwnerPointer(),
|
||||
name = name,
|
||||
index = typeParameters.indexOf(firSymbol),
|
||||
)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
|
||||
+56
@@ -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.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForDeclaration
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.KtFirTypeParameterSymbolPointer
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.pointers.requireOwnerPointer
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
|
||||
|
||||
/**
|
||||
* [KtFirTypeParameterSymbolBase] provides shared implementations for [KtFirTypeParameterSymbol] and [KtFirPsiJavaTypeParameterSymbol].
|
||||
*/
|
||||
internal sealed class KtFirTypeParameterSymbolBase : KtTypeParameterSymbol(), KtFirSymbol<FirTypeParameterSymbol> {
|
||||
override val annotationsList: KtAnnotationsList
|
||||
get() = withValidityAssertion {
|
||||
KtFirAnnotationListForDeclaration.create(firSymbol, analysisSession.useSiteSession, token)
|
||||
}
|
||||
|
||||
override val upperBounds: List<KtType> by cached {
|
||||
firSymbol.resolvedBounds.mapNotNull { type ->
|
||||
if (type.isNullableAny) return@mapNotNull null
|
||||
builder.typeBuilder.buildKtType(type)
|
||||
}
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
override fun createPointer(): KtSymbolPointer<KtTypeParameterSymbol> = withValidityAssertion {
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource<KtTypeParameterSymbol>(this)?.let { return it }
|
||||
|
||||
val containingDeclarationSymbol = firSymbol.containingDeclarationSymbol
|
||||
val typeParameters = containingDeclarationSymbol.typeParameterSymbols
|
||||
requireNotNull(typeParameters) { "Containing declaration symbol: ${containingDeclarationSymbol::class.simpleName}" }
|
||||
|
||||
KtFirTypeParameterSymbolPointer(
|
||||
ownerPointer = requireOwnerPointer(),
|
||||
name = name,
|
||||
index = typeParameters.indexOf(firSymbol),
|
||||
)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = symbolEquals(other)
|
||||
override fun hashCode(): Int = symbolHashCode()
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.symbols.markers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -20,11 +19,4 @@ public interface KtNamedSymbol : KtPossiblyNamedSymbol {
|
||||
|
||||
public interface KtSymbolWithTypeParameters : KtSymbol {
|
||||
public val typeParameters: List<KtTypeParameterSymbol>
|
||||
|
||||
/**
|
||||
* The names of [typeParameters]. Using this property should be preferred if only the names of type parameters are needed, because some
|
||||
* symbol implementations may avoid building the full list of type parameters.
|
||||
*/
|
||||
public val typeParameterNames: List<Name>
|
||||
get() = withValidityAssertion { typeParameters.map { it.name } }
|
||||
}
|
||||
Reference in New Issue
Block a user