[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.analysis.utils.classIdIfNonLocal
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
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.classKind
|
||||||
import org.jetbrains.kotlin.fir.java.modality
|
import org.jetbrains.kotlin.fir.java.modality
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
@@ -82,16 +83,21 @@ internal class KtFirPsiJavaClassSymbol(
|
|||||||
psi.containingClass?.let { KtFirPsiJavaClassSymbol(it, analysisSession) }
|
psi.containingClass?.let { KtFirPsiJavaClassSymbol(it, analysisSession) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val typeParameterNames: List<Name> by cached {
|
override val typeParameters: List<KtTypeParameterSymbol> by cached {
|
||||||
// The parent Java class might contribute `FirOuterClassTypeParameterRef`s to the FIR class's type parameters (see
|
// The parent Java class might contribute type parameters to the Java type parameter stack, but for this KtSymbol, parent type
|
||||||
// `FirJavaFacade.createFirJavaClass`), but since they are filtered out by `createRegularKtTypeParameters`, we do not need to
|
// parameters aren't relevant.
|
||||||
// include them in the list of type parameter names.
|
psi.typeParameters.mapIndexed { index, psiTypeParameter ->
|
||||||
javaClass.typeParameters.map { it.name }
|
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?>
|
val annotationSimpleNames: List<String?>
|
||||||
get() = withValidityAssertion { psi.annotations.map { it.nameReferenceElement?.referenceName } }
|
get() = withValidityAssertion { psi.annotations.map { it.nameReferenceElement?.referenceName } }
|
||||||
|
|
||||||
@@ -122,11 +128,6 @@ internal class KtFirPsiJavaClassSymbol(
|
|||||||
firClassSymbol
|
firClassSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
override val typeParameters: List<KtTypeParameterSymbol> by cached {
|
|
||||||
if (hasTypeParameters) firSymbol.createRegularKtTypeParameters(builder)
|
|
||||||
else emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val annotationsList: KtAnnotationsList by cached {
|
override val annotationsList: KtAnnotationsList by cached {
|
||||||
if (hasAnnotations) KtFirAnnotationListForDeclaration.create(firSymbol, analysisSession.useSiteSession, token)
|
if (hasAnnotations) KtFirAnnotationListForDeclaration.create(firSymbol, analysisSession.useSiteSession, token)
|
||||||
else KtEmptyAnnotationsList(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
|
package org.jetbrains.kotlin.analysis.api.fir.symbols
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
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.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.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.fir.utils.cached
|
||||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
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.symbols.impl.FirTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.isNullableAny
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
internal class KtFirTypeParameterSymbol(
|
internal class KtFirTypeParameterSymbol(
|
||||||
override val firSymbol: FirTypeParameterSymbol,
|
override val firSymbol: FirTypeParameterSymbol,
|
||||||
override val analysisSession: KtFirAnalysisSession,
|
override val analysisSession: KtFirAnalysisSession,
|
||||||
) : KtTypeParameterSymbol(), KtFirSymbol<FirTypeParameterSymbol> {
|
) : KtFirTypeParameterSymbolBase() {
|
||||||
override val token: KtLifetimeToken get() = builder.token
|
override val token: KtLifetimeToken get() = builder.token
|
||||||
override val psi: PsiElement? by cached { firSymbol.findPsi() }
|
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 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 variance: Variance get() = withValidityAssertion { firSymbol.variance }
|
||||||
override val isReified: Boolean get() = withValidityAssertion { firSymbol.isReified }
|
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
|
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.KtSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -20,11 +19,4 @@ public interface KtNamedSymbol : KtPossiblyNamedSymbol {
|
|||||||
|
|
||||||
public interface KtSymbolWithTypeParameters : KtSymbol {
|
public interface KtSymbolWithTypeParameters : KtSymbol {
|
||||||
public val typeParameters: List<KtTypeParameterSymbol>
|
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