[SLC] support non-psi classes

^KT-54051
This commit is contained in:
Dmitrii Gridin
2022-11-26 16:20:02 +01:00
committed by Space Team
parent 812e0413c2
commit 207212e5b8
15 changed files with 614 additions and 272 deletions
@@ -97,36 +97,15 @@ public class KtPsiBasedSymbolPointer<S : KtSymbol> private constructor(
public fun KtElement.symbolPointer(): KtSymbolPointer<KtSymbol> = KtPsiBasedSymbolPointer(this, KtSymbol::class)
public inline fun <reified S : KtSymbol> KtElement.symbolPointerOfType(): KtSymbolPointer<S> = KtPsiBasedSymbolPointer(this, S::class)
public fun KtFile.symbolPointer(): KtSymbolPointer<KtFileSymbol> = KtPsiBasedSymbolPointer(this, KtFileSymbol::class)
public fun KtParameter.symbolPointer(): KtSymbolPointer<KtVariableLikeSymbol> = KtPsiBasedSymbolPointer(this, KtVariableLikeSymbol::class)
public fun KtTypeAlias.symbolPointer(): KtSymbolPointer<KtTypeAliasSymbol> = KtPsiBasedSymbolPointer(this, KtTypeAliasSymbol::class)
public fun KtEnumEntry.symbolPointer(): KtSymbolPointer<KtEnumEntrySymbol> = KtPsiBasedSymbolPointer(this, KtEnumEntrySymbol::class)
public fun KtProperty.symbolPointer(): KtSymbolPointer<KtVariableSymbol> = KtPsiBasedSymbolPointer(this, KtVariableSymbol::class)
public fun KtNamedFunction.symbolPointer(): KtSymbolPointer<KtFunctionLikeSymbol> {
return KtPsiBasedSymbolPointer(this, KtFunctionLikeSymbol::class)
}
public fun KtConstructor<*>.symbolPointer(): KtSymbolPointer<KtConstructorSymbol> {
return KtPsiBasedSymbolPointer(this, KtConstructorSymbol::class)
}
public fun KtTypeParameter.symbolPointer(): KtSymbolPointer<KtTypeParameterSymbol> {
return KtPsiBasedSymbolPointer(this, KtTypeParameterSymbol::class)
}
public fun KtFunctionLiteral.symbolPointer(): KtSymbolPointer<KtAnonymousFunctionSymbol> {
return KtPsiBasedSymbolPointer(this, KtAnonymousFunctionSymbol::class)
}
public fun KtObjectLiteralExpression.symbolPointer(): KtSymbolPointer<KtAnonymousObjectSymbol> {
return KtPsiBasedSymbolPointer(this, KtAnonymousObjectSymbol::class)
}
public fun KtClassOrObject.symbolPointer(): KtSymbolPointer<KtClassOrObjectSymbol> {
return KtPsiBasedSymbolPointer(this, KtClassOrObjectSymbol::class)
}
public fun KtPropertyAccessor.symbolPointer(): KtSymbolPointer<KtPropertyAccessorSymbol> {
return KtPsiBasedSymbolPointer(this, KtPropertyAccessorSymbol::class)
}
public fun KtFile.symbolPointer(): KtSymbolPointer<KtFileSymbol> = symbolPointerOfType()
public fun KtParameter.symbolPointer(): KtSymbolPointer<KtVariableLikeSymbol> = symbolPointerOfType()
public fun KtTypeAlias.symbolPointer(): KtSymbolPointer<KtTypeAliasSymbol> = symbolPointerOfType()
public fun KtEnumEntry.symbolPointer(): KtSymbolPointer<KtEnumEntrySymbol> = symbolPointerOfType()
public fun KtProperty.symbolPointer(): KtSymbolPointer<KtVariableSymbol> = symbolPointerOfType()
public fun KtNamedFunction.symbolPointer(): KtSymbolPointer<KtFunctionLikeSymbol> = symbolPointerOfType()
public fun KtConstructor<*>.symbolPointer(): KtSymbolPointer<KtConstructorSymbol> = symbolPointerOfType()
public fun KtTypeParameter.symbolPointer(): KtSymbolPointer<KtTypeParameterSymbol> = symbolPointerOfType()
public fun KtFunctionLiteral.symbolPointer(): KtSymbolPointer<KtAnonymousFunctionSymbol> = symbolPointerOfType()
public fun KtObjectLiteralExpression.symbolPointer(): KtSymbolPointer<KtAnonymousObjectSymbol> = symbolPointerOfType()
public fun KtPropertyAccessor.symbolPointer(): KtSymbolPointer<KtPropertyAccessorSymbol> = symbolPointerOfType()
public fun KtClassOrObject.symbolPointer(): KtSymbolPointer<KtClassOrObjectSymbol> = symbolPointerOfType()
@@ -5,24 +5,53 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReferenceList
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.isPrivateOrPrivateToThis
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
internal class SymbolLightAnnotationClass(
classOrObject: KtClassOrObject,
ktModule: KtModule,
) : SymbolLightInterfaceOrAnnotationClass(classOrObject, ktModule) {
init {
require(isAnnotation)
internal class SymbolLightAnnotationClass : SymbolLightInterfaceOrAnnotationClass {
constructor(
ktAnalysisSession: KtAnalysisSession,
ktModule: KtModule,
classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : super(
ktAnalysisSession = ktAnalysisSession,
ktModule = ktModule,
classOrObjectSymbol = classOrObjectSymbol,
manager = manager,
) {
require(classOrObjectSymbol.classKind == KtClassKind.ANNOTATION_CLASS)
}
constructor(classOrObject: KtClassOrObject, ktModule: KtModule) : super(classOrObject, ktModule) {
require(classOrObject is KtClass && classOrObject.isAnnotation())
}
private constructor(
classOrObjectDeclaration: KtClassOrObject?,
classOrObjectSymbolPointer: KtSymbolPointer<KtNamedClassOrObjectSymbol>,
ktModule: KtModule,
manager: PsiManager,
) : super(
classOrObjectDeclaration = classOrObjectDeclaration,
classOrObjectSymbolPointer = classOrObjectSymbolPointer,
ktModule = ktModule,
manager = manager,
)
override fun isAnnotationType(): Boolean = true
private val _ownMethods: List<KtLightMethod> by lazyPub {
@@ -41,5 +70,6 @@ internal class SymbolLightAnnotationClass(
override fun getExtendsList(): PsiReferenceList? = null
override fun copy(): SymbolLightClassForClassOrObject = SymbolLightAnnotationClass(classOrObject, ktModule)
override fun copy(): SymbolLightAnnotationClass =
SymbolLightAnnotationClass(classOrObjectDeclaration, classOrObjectSymbolPointer, ktModule, manager)
}
@@ -6,7 +6,10 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.symbols.KtAnonymousObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointerOfType
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.getParentForLocalDeclaration
import org.jetbrains.kotlin.asJava.classes.lazyPub
@@ -17,8 +20,23 @@ import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmFieldAnnotati
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightField
import org.jetbrains.kotlin.psi.KtClassOrObject
internal class SymbolLightAnonymousClass(classOrObject: KtClassOrObject, ktModule: KtModule) :
SymbolLightClassForClassOrObject(classOrObject, ktModule), PsiAnonymousClass {
internal class SymbolLightAnonymousClass : SymbolLightClassForClassOrObject<KtAnonymousObjectSymbol>, PsiAnonymousClass {
constructor(
anonymousObjectDeclaration: KtClassOrObject,
ktModule: KtModule,
) : this(
classOrObjectDeclaration = anonymousObjectDeclaration,
classOrObjectSymbolPointer = anonymousObjectDeclaration.symbolPointerOfType(),
ktModule = ktModule,
manager = anonymousObjectDeclaration.manager,
)
private constructor(
classOrObjectDeclaration: KtClassOrObject?,
classOrObjectSymbolPointer: KtSymbolPointer<KtAnonymousObjectSymbol>,
ktModule: KtModule,
manager: PsiManager,
) : super(classOrObjectDeclaration, classOrObjectSymbolPointer, ktModule, manager)
private val _baseClassType: PsiClassType by lazyPub {
extendsListTypes.firstOrNull()
@@ -43,8 +61,8 @@ internal class SymbolLightAnonymousClass(classOrObject: KtClassOrObject, ktModul
}
}
override fun getExtendsList(): PsiReferenceList = _extendsList
override fun getImplementsList(): PsiReferenceList = _implementsList
override fun getExtendsList(): PsiReferenceList? = _extendsList
override fun getImplementsList(): PsiReferenceList? = _implementsList
override fun getOwnFields(): List<KtLightField> = _ownFields
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
@@ -74,7 +92,7 @@ internal class SymbolLightAnonymousClass(classOrObject: KtClassOrObject, ktModul
isTopLevel = false,
forceStatic = false,
takePropertyVisibility = propertySymbol.hasJvmFieldAnnotation(),
result
result,
)
}
@@ -82,7 +100,7 @@ internal class SymbolLightAnonymousClass(classOrObject: KtClassOrObject, ktModul
}
}
override fun getParent(): PsiElement? = kotlinOrigin.let(::getParentForLocalDeclaration)
override fun getParent(): PsiElement? = kotlinOrigin?.let(::getParentForLocalDeclaration)
override fun getArgumentList(): PsiExpressionList? = null
override fun isInQualifiedNew(): Boolean = false
override fun getName(): String? = null
@@ -93,5 +111,5 @@ internal class SymbolLightAnonymousClass(classOrObject: KtClassOrObject, ktModul
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getQualifiedName(): String? = null
override fun copy() = SymbolLightAnonymousClass(classOrObject, ktModule)
override fun copy() = SymbolLightAnonymousClass(classOrObjectDeclaration, classOrObjectSymbolPointer, ktModule, manager)
}
@@ -5,13 +5,12 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiReferenceList
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointerOfType
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_BASE
@@ -36,7 +35,10 @@ import org.jetbrains.kotlin.light.classes.symbol.toPsiVisibilityForClass
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.resolve.DataClassResolver
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
@@ -44,15 +46,48 @@ import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
internal open class SymbolLightClass(classOrObject: KtClassOrObject, ktModule: KtModule) :
SymbolLightClassForClassOrObject(classOrObject, ktModule) {
init {
internal open class SymbolLightClass : SymbolLightClassForNamedClassOrObject {
constructor(
ktAnalysisSession: KtAnalysisSession,
ktModule: KtModule,
classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : super(
ktAnalysisSession = ktAnalysisSession,
ktModule = ktModule,
classOrObjectSymbol = classOrObjectSymbol,
manager = manager,
) {
require(classOrObjectSymbol.classKind != KtClassKind.INTERFACE && classOrObjectSymbol.classKind != KtClassKind.ANNOTATION_CLASS)
}
constructor(
classOrObject: KtClassOrObject,
ktModule: KtModule,
) : this(
classOrObjectDeclaration = classOrObject,
classOrObjectSymbolPointer = classOrObject.symbolPointerOfType(),
ktModule = ktModule,
manager = classOrObject.manager,
) {
require(classOrObject !is KtClass || !classOrObject.isInterface() && !classOrObject.isAnnotation())
}
protected constructor(
classOrObjectDeclaration: KtClassOrObject?,
classOrObjectSymbolPointer: KtSymbolPointer<KtNamedClassOrObjectSymbol>,
ktModule: KtModule,
manager: PsiManager,
) : super(
classOrObjectDeclaration = classOrObjectDeclaration,
classOrObjectSymbolPointer = classOrObjectSymbolPointer,
ktModule = ktModule,
manager = manager,
)
private val _modifierList: PsiModifierList? by lazy {
val lazyModifiers = lazy {
withNamedClassOrObjectSymbol { classOrObjectSymbol ->
withClassOrObjectSymbol { classOrObjectSymbol ->
buildSet {
add(classOrObjectSymbol.toPsiVisibilityForClass(isNested = !isTopLevel))
addIfNotNull(classOrObjectSymbol.computeSimpleModality())
@@ -64,7 +99,7 @@ internal open class SymbolLightClass(classOrObject: KtClassOrObject, ktModule: K
}
val lazyAnnotations = lazyPub {
withNamedClassOrObjectSymbol { classOrObjectSymbol ->
withClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.computeAnnotations(
parent = this@SymbolLightClass,
nullability = NullabilityType.Unknown,
@@ -95,7 +130,7 @@ internal open class SymbolLightClass(classOrObject: KtClassOrObject, ktModule: K
}
private val _ownMethods: List<KtLightMethod> by lazyPub {
withNamedClassOrObjectSymbol { classOrObjectSymbol ->
withClassOrObjectSymbol { classOrObjectSymbol ->
val result = mutableListOf<KtLightMethod>()
val declaredMemberScope = classOrObjectSymbol.getDeclaredMemberScope()
@@ -138,12 +173,16 @@ internal open class SymbolLightClass(classOrObject: KtClassOrObject, ktModule: K
fun createMethodFromAny(ktFunctionSymbol: KtFunctionSymbol) {
// Similar to `copy`, synthetic members from `Any` should refer to `data` class as origin, not the function in `Any`.
val lightMemberOrigin = LightMemberOriginForDeclaration(classOrObject, JvmDeclarationOriginKind.OTHER)
val lightMemberOrigin = classOrObjectDeclaration?.let { LightMemberOriginForDeclaration(it, JvmDeclarationOriginKind.OTHER) }
result.add(
SymbolLightSimpleMethod(
ktAnalysisSession = this@ktAnalysisSession,
ktFunctionSymbol, lightMemberOrigin, this, METHOD_INDEX_BASE, false,
suppressStatic = false
ktFunctionSymbol,
lightMemberOrigin,
this,
METHOD_INDEX_BASE,
false,
suppressStatic = false,
)
)
}
@@ -189,8 +228,8 @@ internal open class SymbolLightClass(classOrObject: KtClassOrObject, ktModule: K
context(ktAnalysisSession@KtAnalysisSession)
private fun addDelegatesToInterfaceMethods(result: MutableList<KtLightMethod>, classOrObjectSymbol: KtNamedClassOrObjectSymbol) {
fun createDelegateMethod(ktFunctionSymbol: KtFunctionSymbol) {
val kotlinOrigin = ktFunctionSymbol.psiSafe<KtDeclaration>() ?: classOrObject
val lightMemberOrigin = LightMemberOriginForDeclaration(kotlinOrigin, JvmDeclarationOriginKind.DELEGATION)
val kotlinOrigin = ktFunctionSymbol.psiSafe<KtDeclaration>() ?: classOrObjectDeclaration
val lightMemberOrigin = kotlinOrigin?.let { LightMemberOriginForDeclaration(it, JvmDeclarationOriginKind.DELEGATION) }
result.add(
SymbolLightSimpleMethod(
ktAnalysisSession = this@ktAnalysisSession,
@@ -213,18 +252,18 @@ internal open class SymbolLightClass(classOrObject: KtClassOrObject, ktModule: K
}
private val _ownFields: List<KtLightField> by lazyPub {
withNamedClassOrObjectSymbol { classOrObjectSymbol ->
withClassOrObjectSymbol { classOrObjectSymbol ->
val result = mutableListOf<KtLightField>()
// First, add static fields: companion object and fields from companion object
addCompanionObjectFieldIfNeeded(result)
addFieldsFromCompanionIfNeeded(result)
addCompanionObjectFieldIfNeeded(result, classOrObjectSymbol)
addFieldsFromCompanionIfNeeded(result, classOrObjectSymbol)
// Then, add instance fields: properties from parameters, and then member properties
addPropertyBackingFields(result, classOrObjectSymbol)
// Next, add INSTANCE field if non-local named object
addInstanceFieldIfNeeded(result)
addInstanceFieldIfNeeded(result, classOrObjectSymbol)
// Last, add fields for enum entries
addFieldsForEnumEntries(result, classOrObjectSymbol)
@@ -271,40 +310,41 @@ internal open class SymbolLightClass(classOrObject: KtClassOrObject, ktModule: K
propertyGroups[false]?.forEach(::addPropertyBackingField)
}
private fun addInstanceFieldIfNeeded(result: MutableList<KtLightField>) {
if (isNamedObject && !isLocal) {
result.add(
SymbolLightFieldForObject(
objectDeclaration = classOrObject as KtObjectDeclaration,
containingClass = this@SymbolLightClass,
name = JvmAbi.INSTANCE_FIELD,
lightMemberOrigin = null
)
context(ktAnalysisSession@KtAnalysisSession)
private fun addInstanceFieldIfNeeded(result: MutableList<KtLightField>, namedClassOrObjectSymbol: KtNamedClassOrObjectSymbol) {
if (!isNamedObject || isLocal) return
result.add(
SymbolLightFieldForObject(
ktAnalysisSession = this@ktAnalysisSession,
objectSymbol = namedClassOrObjectSymbol,
containingClass = this,
name = JvmAbi.INSTANCE_FIELD,
lightMemberOrigin = null,
)
}
)
}
context(KtAnalysisSession)
context(ktAnalysisSession@KtAnalysisSession)
private fun addFieldsForEnumEntries(result: MutableList<KtLightField>, classOrObjectSymbol: KtNamedClassOrObjectSymbol) {
if (isEnum) {
classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtEnumEntrySymbol>()
.mapNotNullTo(result) {
val enumEntry = it.psiSafe<KtEnumEntry>()
val name = enumEntry?.name ?: return@mapNotNullTo null
SymbolLightFieldForEnumEntry(
enumEntry = enumEntry,
enumEntryName = name,
containingClass = this@SymbolLightClass,
lightMemberOrigin = null,
)
}
}
if (!isEnum) return
classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtEnumEntrySymbol>()
.mapNotNullTo(result) {
val enumEntry = it.psiSafe<KtEnumEntry>()
val name = enumEntry?.name ?: return@mapNotNullTo null
SymbolLightFieldForEnumEntry(
enumEntry = enumEntry,
enumEntryName = name,
containingClass = this@SymbolLightClass,
)
}
}
override fun isInterface(): Boolean = false
override fun isAnnotationType(): Boolean = false
override fun copy(): SymbolLightClass = SymbolLightClass(classOrObject, ktModule)
override fun copy(): SymbolLightClass = SymbolLightClass(classOrObjectDeclaration, classOrObjectSymbolPointer, ktModule, manager)
}
@@ -8,30 +8,24 @@ package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.*
import com.intellij.psi.impl.InheritanceImplUtil
import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.SearchScope
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.StubElement
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointer
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.getParentForLocalDeclaration
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.light.classes.symbol.analyzeForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.*
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasDeprecatedAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.light.classes.symbol.basicIsEquivalentTo
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForObject
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForProperty
import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightTypeParameterList
import org.jetbrains.kotlin.light.classes.symbol.withSymbol
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassBody
@@ -39,32 +33,76 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtClassOrObject, ktModule: KtModule) :
SymbolLightClassBase(ktModule, classOrObject.manager),
abstract class SymbolLightClassForClassOrObject<SType : KtClassOrObjectSymbol> protected constructor(
internal val classOrObjectDeclaration: KtClassOrObject?,
internal val classOrObjectSymbolPointer: KtSymbolPointer<SType>,
ktModule: KtModule,
manager: PsiManager,
) : SymbolLightClassBase(ktModule, manager),
StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>> {
private val classOrObjectSymbolPointer: KtSymbolPointer<KtClassOrObjectSymbol> = classOrObject.symbolPointer()
constructor(
ktAnalysisSession: KtAnalysisSession,
ktModule: KtModule,
classOrObjectSymbol: SType,
manager: PsiManager,
) : this(
classOrObjectDeclaration = classOrObjectSymbol.sourcePsiSafe(),
classOrObjectSymbolPointer = with(ktAnalysisSession) {
@Suppress("UNCHECKED_CAST")
classOrObjectSymbol.createPointer() as KtSymbolPointer<SType>
},
ktModule = ktModule,
manager = manager,
)
protected fun <T> withClassOrObjectSymbol(action: KtAnalysisSession.(KtClassOrObjectSymbol) -> T): T {
return classOrObjectSymbolPointer.withSymbol(ktModule, action)
override val kotlinOrigin: KtClassOrObject? get() = classOrObjectDeclaration
protected fun <T> withClassOrObjectSymbol(action: KtAnalysisSession.(SType) -> T): T =
classOrObjectSymbolPointer.withSymbol(ktModule, action)
override val isTopLevel: Boolean by lazy {
classOrObjectDeclaration?.isTopLevel() ?: withClassOrObjectSymbol { it.symbolKind == KtSymbolKind.TOP_LEVEL }
}
protected fun <T> withNamedClassOrObjectSymbol(action: KtAnalysisSession.(KtNamedClassOrObjectSymbol) -> T): T =
analyzeForLightClasses(ktModule) {
action(requireNotNull(classOrObject.getNamedClassOrObjectSymbol()))
internal val isCompanionObject: Boolean by lazy {
classOrObjectDeclaration?.let { it is KtObjectDeclaration && it.isCompanion() } ?: withClassOrObjectSymbol {
it.classKind == KtClassKind.COMPANION_OBJECT
}
}
override val isTopLevel: Boolean get() = classOrObject.isTopLevel()
internal val isCompanionObject: Boolean get() = classOrObject is KtObjectDeclaration && classOrObject.isCompanion()
internal val isLocal: Boolean get() = classOrObject.isLocal
internal val isNamedObject: Boolean get() = classOrObject is KtObjectDeclaration && !classOrObject.isCompanion()
internal val isObject: Boolean get() = classOrObject is KtObjectDeclaration
internal val isInterface: Boolean get() = classOrObject is KtClass && classOrObject.isInterface()
internal val isAnnotation: Boolean get() = classOrObject is KtClass && classOrObject.isAnnotation()
internal val isEnum: Boolean get() = classOrObject is KtClass && classOrObject.isEnum()
internal val isLocal: Boolean by lazy {
classOrObjectDeclaration?.isLocal ?: withClassOrObjectSymbol { it.symbolKind == KtSymbolKind.LOCAL }
}
internal val isNamedObject: Boolean by lazy {
classOrObjectDeclaration?.let { it is KtObjectDeclaration && !it.isCompanion() } ?: withClassOrObjectSymbol {
it.classKind == KtClassKind.OBJECT
}
}
internal val isObject: Boolean by lazy {
classOrObjectDeclaration?.let { it is KtObjectDeclaration } ?: withClassOrObjectSymbol { it.classKind.isObject }
}
internal val isInterface: Boolean by lazy {
classOrObjectDeclaration?.let { it is KtClass && it.isInterface() } ?: withClassOrObjectSymbol {
it.classKind == KtClassKind.INTERFACE
}
}
internal val isAnnotation: Boolean by lazy {
classOrObjectDeclaration?.let { it is KtClass && it.isAnnotation() } ?: withClassOrObjectSymbol {
it.classKind == KtClassKind.ANNOTATION_CLASS
}
}
internal val isEnum: Boolean by lazy {
classOrObjectDeclaration?.let { it is KtClass && it.isEnum() } ?: withClassOrObjectSymbol {
it.classKind == KtClassKind.ENUM_CLASS
}
}
private val _isDeprecated: Boolean by lazy {
withClassOrObjectSymbol { it.hasDeprecatedAnnotation() }
@@ -77,7 +115,7 @@ abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtC
abstract override fun getOwnMethods(): List<PsiMethod>
private val _identifier: PsiIdentifier by lazy {
KtLightIdentifier(this, classOrObject)
KtLightIdentifier(this, classOrObjectDeclaration)
}
override fun getNameIdentifier(): PsiIdentifier? = _identifier
@@ -91,96 +129,29 @@ abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtC
owner = this,
symbolWithTypeParameterPointer = classOrObjectSymbolPointer,
ktModule = ktModule,
ktDeclaration = classOrObject,
ktDeclaration = classOrObjectDeclaration,
)
}
}
override fun hasTypeParameters(): Boolean = classOrObject.typeParameters.isNotEmpty()
override fun hasTypeParameters(): Boolean = hasTypeParameters(ktModule, classOrObjectDeclaration, classOrObjectSymbolPointer)
override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList
override fun getTypeParameters(): Array<PsiTypeParameter> = _typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
private val _ownInnerClasses: List<SymbolLightClassBase> by lazyPub {
withClassOrObjectSymbol {
it.createInnerClasses(this@SymbolLightClassForClassOrObject, classOrObject)
it.createInnerClasses(manager, this@SymbolLightClassForClassOrObject, classOrObjectDeclaration)
}
}
override fun getOwnInnerClasses(): List<PsiClass> = _ownInnerClasses
override fun getTextOffset(): Int = classOrObject.textOffset
override fun getStartOffsetInParent(): Int = classOrObject.startOffsetInParent
override fun getTextOffset(): Int = classOrObjectDeclaration?.textOffset ?: -1
override fun getStartOffsetInParent(): Int = classOrObjectDeclaration?.startOffsetInParent ?: -1
override fun isWritable() = false
override val kotlinOrigin: KtClassOrObject = classOrObject
protected fun addMethodsFromCompanionIfNeeded(
result: MutableList<KtLightMethod>,
): Unit = withNamedClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.companionObject?.run {
val methods = getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtFunctionSymbol>()
.filter { it.hasJvmStaticAnnotation() }
createMethods(methods, result)
val properties = getDeclaredMemberScope().getCallableSymbols().filterIsInstance<KtPropertySymbol>()
properties.forEach { property ->
createPropertyAccessors(
result,
property,
isTopLevel = false,
onlyJvmStatic = true
)
}
}
}
protected fun addCompanionObjectFieldIfNeeded(result: MutableList<KtLightField>) {
classOrObject.companionObjects.forEach {
result.add(
SymbolLightFieldForObject(
objectDeclaration = it,
containingClass = this@SymbolLightClassForClassOrObject,
name = it.name ?: return@forEach,
lightMemberOrigin = null,
)
)
}
}
protected fun addFieldsFromCompanionIfNeeded(
result: MutableList<KtLightField>,
): Unit = withNamedClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.companionObject
?.getDeclaredMemberScope()
?.getCallableSymbols()
?.filterIsInstance<KtPropertySymbol>()
?.applyIf(isInterface) {
filter { it.isConstOrJvmField }
}
?.mapTo(result) {
SymbolLightFieldForProperty(
ktAnalysisSession = this,
propertySymbol = it,
fieldName = it.name.asString(),
containingClass = this@SymbolLightClassForClassOrObject,
lightMemberOrigin = null,
isTopLevel = false,
forceStatic = true,
takePropertyVisibility = it.isConstOrJvmField,
)
}
}
private val KtPropertySymbol.isConstOrJvmField: Boolean
get() = isConst || hasJvmFieldAnnotation()
private val KtPropertySymbol.isConst: Boolean
get() = (this as? KtKotlinPropertySymbol)?.isConst == true
override fun getNavigationElement(): PsiElement = classOrObject
override fun getNavigationElement(): PsiElement = classOrObjectDeclaration ?: this
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another) ||
@@ -188,13 +159,21 @@ abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtC
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is SymbolLightClassForClassOrObject<*> || other.ktModule != ktModule || other.manager != manager) return false
if (classOrObjectDeclaration != null) {
return other.classOrObjectDeclaration == classOrObjectDeclaration
}
return other?.safeAs<SymbolLightClassForClassOrObject>()?.classOrObject == classOrObject
return other.classOrObjectDeclaration == null && compareSymbolPointers(
ktModule,
classOrObjectSymbolPointer,
other.classOrObjectSymbolPointer,
)
}
override fun hashCode(): Int = classOrObject.hashCode()
override fun hashCode(): Int = classOrObjectDeclaration.hashCode()
override fun getName(): String? = classOrObject.name
override fun getName(): String? = classOrObjectDeclaration?.name
override fun hasModifierProperty(@NonNls name: String): Boolean = modifierList?.hasModifierProperty(name) ?: false
@@ -202,17 +181,17 @@ abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtC
override fun isAnnotationType(): Boolean = isAnnotation
override fun isEnum(): Boolean = isEnum
override fun isValid(): Boolean = classOrObject.isValid
override fun isValid(): Boolean = classOrObjectDeclaration?.isValid ?: classOrObjectSymbolPointer.isValid(ktModule)
override fun toString() = "${this::class.java.simpleName}:${classOrObject.getDebugText()}"
override fun toString() = "${this::class.java.simpleName}:${classOrObjectDeclaration?.getDebugText()}"
override fun getUseScope(): SearchScope = classOrObject.useScope
override fun getElementType(): IStubElementType<out StubElement<*>, *>? = classOrObject.elementType
override fun getStub(): KotlinClassOrObjectStub<out KtClassOrObject>? = classOrObject.stub
override fun getUseScope(): SearchScope = classOrObjectDeclaration?.useScope ?: GlobalSearchScope.projectScope(project)
override fun getElementType(): IStubElementType<out StubElement<*>, *>? = classOrObjectDeclaration?.elementType
override fun getStub(): KotlinClassOrObjectStub<out KtClassOrObject>? = classOrObjectDeclaration?.stub
override val originKind: LightClassOriginKind get() = LightClassOriginKind.SOURCE
override fun getQualifiedName() = classOrObject.fqName?.asString()
override fun getQualifiedName(): String? = classOrObjectDeclaration?.fqName?.asString()
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
override fun getSuperClass(): PsiClass? = PsiClassImplUtil.getSuperClass(this)
@@ -220,7 +199,7 @@ abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtC
override fun getSuperTypes(): Array<PsiClassType> = PsiClassImplUtil.getSuperTypes(this)
override fun getContainingClass(): PsiClass? {
val containingBody = classOrObject.parent as? KtClassBody
val containingBody = classOrObjectDeclaration?.parent as? KtClassBody
val containingClass = containingBody?.parent as? KtClassOrObject
containingClass?.let { return it.toLightClass() }
return null
@@ -228,7 +207,7 @@ abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtC
override fun getParent(): PsiElement? {
if (isLocal) {
return classOrObject.let(::getParentForLocalDeclaration)
return classOrObjectDeclaration?.let(::getParentForLocalDeclaration)
}
return containingClass ?: containingFile
@@ -239,5 +218,5 @@ abstract class SymbolLightClassForClassOrObject(protected val classOrObject: KtC
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean =
baseClass?.let { InheritanceImplUtil.isInheritorDeep(this, it, classToByPass) } ?: false
abstract override fun copy(): SymbolLightClassForClassOrObject
abstract override fun copy(): SymbolLightClassForClassOrObject<*>
}
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointer
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.KotlinSuperTypeListBuilder
@@ -20,7 +22,12 @@ internal class SymbolLightClassForEnumEntry(
private val enumConstant: SymbolLightFieldForEnumEntry,
private val enumClass: SymbolLightClass,
ktModule: KtModule,
) : SymbolLightClass(enumConstant.kotlinOrigin, ktModule), PsiEnumConstantInitializer {
) : SymbolLightClass(
enumConstant.kotlinOrigin,
symbolPointer<KtNamedClassOrObjectSymbol> { null },
ktModule,
enumClass.manager,
), PsiEnumConstantInitializer {
override fun getBaseClassType(): PsiClassType = enumConstant.type as PsiClassType //???TODO
override fun getBaseClassReference(): PsiJavaCodeReferenceElement =
@@ -63,7 +70,7 @@ internal class SymbolLightClassForEnumEntry(
} ?: return@lazyPub null
KotlinSuperTypeListBuilder(
kotlinOrigin = enumClass.kotlinOrigin.getSuperTypeList(),
kotlinOrigin = enumClass.kotlinOrigin?.getSuperTypeList(),
manager = manager,
language = language,
role = PsiReferenceList.Role.EXTENDS_LIST
@@ -11,7 +11,12 @@ import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassM
import org.jetbrains.kotlin.load.java.JvmAbi
internal class SymbolLightClassForInterfaceDefaultImpls(private val containingClass: SymbolLightInterfaceClass) :
SymbolLightInterfaceClass(containingClass.kotlinOrigin, containingClass.ktModule) {
SymbolLightInterfaceClass(
containingClass.classOrObjectDeclaration,
containingClass.classOrObjectSymbolPointer,
containingClass.ktModule,
containingClass.manager,
) {
override fun getQualifiedName(): String? = containingClass.qualifiedName?.let { it + ".${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}" }
override fun getName() = JvmAbi.DEFAULT_IMPLS_CLASS_NAME
@@ -19,6 +24,11 @@ internal class SymbolLightClassForInterfaceDefaultImpls(private val containingCl
override fun copy() = SymbolLightClassForInterfaceDefaultImpls(containingClass)
override fun equals(other: Any?): Boolean = this === other ||
other is SymbolLightClassForInterfaceDefaultImpls && other.containingClass == containingClass
override fun hashCode(): Int = containingClass.hashCode()
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
@@ -0,0 +1,122 @@
/*
* Copyright 2010-2022 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.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForObject
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForProperty
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
abstract class SymbolLightClassForNamedClassOrObject : SymbolLightClassForClassOrObject<KtNamedClassOrObjectSymbol> {
constructor(
ktAnalysisSession: KtAnalysisSession,
ktModule: KtModule,
classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : super(
ktAnalysisSession = ktAnalysisSession,
ktModule = ktModule,
classOrObjectSymbol = classOrObjectSymbol,
manager = manager,
)
protected constructor(
classOrObjectDeclaration: KtClassOrObject?,
classOrObjectSymbolPointer: KtSymbolPointer<KtNamedClassOrObjectSymbol>,
ktModule: KtModule,
manager: PsiManager,
) : super(
classOrObjectDeclaration = classOrObjectDeclaration,
classOrObjectSymbolPointer = classOrObjectSymbolPointer,
ktModule = ktModule,
manager = manager
)
protected fun addMethodsFromCompanionIfNeeded(
result: MutableList<KtLightMethod>,
): Unit = withClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.companionObject?.run {
val methods = getDeclaredMemberScope().getCallableSymbols()
.filterIsInstance<KtFunctionSymbol>()
.filter { it.hasJvmStaticAnnotation() }
createMethods(methods, result)
val properties = getDeclaredMemberScope().getCallableSymbols().filterIsInstance<KtPropertySymbol>()
properties.forEach { property ->
createPropertyAccessors(
result,
property,
isTopLevel = false,
onlyJvmStatic = true
)
}
}
}
private val KtPropertySymbol.isConstOrJvmField: Boolean
get() = isConst || hasJvmFieldAnnotation()
private val KtPropertySymbol.isConst: Boolean
get() = (this as? KtKotlinPropertySymbol)?.isConst == true
context(ktAnalysisSession@KtAnalysisSession)
protected fun addFieldsFromCompanionIfNeeded(
result: MutableList<KtLightField>,
classOrObjectSymbol: KtNamedClassOrObjectSymbol,
) {
classOrObjectSymbol.companionObject
?.getDeclaredMemberScope()
?.getCallableSymbols()
?.filterIsInstance<KtPropertySymbol>()
?.applyIf(isInterface) {
filter { it.isConstOrJvmField }
}
?.mapTo(result) {
SymbolLightFieldForProperty(
ktAnalysisSession = this@ktAnalysisSession,
propertySymbol = it,
fieldName = it.name.asString(),
containingClass = this,
lightMemberOrigin = null,
isTopLevel = false,
forceStatic = true,
takePropertyVisibility = it.isConstOrJvmField,
)
}
}
context(ktAnalysisSession@KtAnalysisSession)
protected fun addCompanionObjectFieldIfNeeded(result: MutableList<KtLightField>, classOrObjectSymbol: KtNamedClassOrObjectSymbol) {
val companionObjectSymbols: List<KtNamedClassOrObjectSymbol>? = classOrObjectDeclaration?.companionObjects?.mapNotNull {
it.getNamedClassOrObjectSymbol()
} ?: classOrObjectSymbol.companionObject?.let(::listOf)
companionObjectSymbols?.forEach {
result.add(
SymbolLightFieldForObject(
ktAnalysisSession = this@ktAnalysisSession,
objectSymbol = it,
containingClass = this,
name = it.name.asString(),
lightMemberOrigin = null,
)
)
}
}
}
@@ -5,9 +5,13 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointerOfType
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
@@ -16,11 +20,31 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
internal class SymbolLightInlineClass(classOrObject: KtClassOrObject, ktModule: KtModule) : SymbolLightClass(classOrObject, ktModule) {
init {
internal class SymbolLightInlineClass : SymbolLightClass {
constructor(
classOrObject: KtClassOrObject,
ktModule: KtModule,
) : this(
classOrObjectDeclaration = classOrObject,
classOrObjectSymbolPointer = classOrObject.symbolPointerOfType(),
ktModule = ktModule,
manager = classOrObject.manager,
) {
require(classOrObject.hasModifier(KtTokens.INLINE_KEYWORD))
}
private constructor(
classOrObjectDeclaration: KtClassOrObject?,
classOrObjectSymbolPointer: KtSymbolPointer<KtNamedClassOrObjectSymbol>,
ktModule: KtModule,
manager: PsiManager,
) : super(
classOrObjectDeclaration = classOrObjectDeclaration,
classOrObjectSymbolPointer = classOrObjectSymbolPointer,
ktModule = ktModule,
manager = manager,
)
private val _ownMethods: List<KtLightMethod> by lazyPub {
withClassOrObjectSymbol { classOrObjectSymbol ->
val result = mutableListOf<KtLightMethod>()
@@ -59,7 +83,7 @@ internal class SymbolLightInlineClass(classOrObject: KtClassOrObject, ktModule:
}
private val _ownFields: List<KtLightField> by lazyPub {
withNamedClassOrObjectSymbol { classOrObjectSymbol ->
withClassOrObjectSymbol { classOrObjectSymbol ->
mutableListOf<KtLightField>().apply {
addPropertyBackingFields(this, classOrObjectSymbol)
}
@@ -70,5 +94,6 @@ internal class SymbolLightInlineClass(classOrObject: KtClassOrObject, ktModule:
override fun getOwnFields(): List<KtLightField> = _ownFields
override fun copy(): SymbolLightInlineClass = SymbolLightInlineClass(classOrObject, ktModule)
override fun copy(): SymbolLightInlineClass =
SymbolLightInlineClass(classOrObjectDeclaration, classOrObjectSymbolPointer, ktModule, manager)
}
@@ -5,23 +5,52 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReferenceList
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.isPrivateOrPrivateToThis
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
internal open class SymbolLightInterfaceClass(
classOrObject: KtClassOrObject,
ktModule: KtModule,
) : SymbolLightInterfaceOrAnnotationClass(classOrObject, ktModule) {
init {
require(isInterface)
internal open class SymbolLightInterfaceClass : SymbolLightInterfaceOrAnnotationClass {
constructor(
ktAnalysisSession: KtAnalysisSession,
ktModule: KtModule,
classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : super(
ktAnalysisSession = ktAnalysisSession,
ktModule = ktModule,
classOrObjectSymbol = classOrObjectSymbol,
manager = manager,
) {
require(classOrObjectSymbol.classKind == KtClassKind.INTERFACE)
}
constructor(classOrObject: KtClassOrObject, ktModule: KtModule) : super(classOrObject, ktModule) {
require(classOrObject is KtClass && classOrObject.isInterface())
}
protected constructor(
classOrObjectDeclaration: KtClassOrObject?,
classOrObjectSymbolPointer: KtSymbolPointer<KtNamedClassOrObjectSymbol>,
ktModule: KtModule,
manager: PsiManager,
) : super(
classOrObjectDeclaration = classOrObjectDeclaration,
classOrObjectSymbolPointer = classOrObjectSymbolPointer,
ktModule = ktModule,
manager = manager,
)
private val _ownMethods: List<KtLightMethod> by lazyPub {
withClassOrObjectSymbol { classOrObjectSymbol ->
val result = mutableListOf<KtLightMethod>()
@@ -38,7 +67,8 @@ internal open class SymbolLightInterfaceClass(
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
override fun copy(): SymbolLightClassForClassOrObject = SymbolLightInterfaceClass(classOrObject, ktModule)
override fun copy(): SymbolLightInterfaceClass =
SymbolLightInterfaceClass(classOrObjectDeclaration, classOrObjectSymbolPointer, ktModule, manager)
private val _extendsList: PsiReferenceList by lazyPub {
withClassOrObjectSymbol { classOrObjectSymbol ->
@@ -5,9 +5,15 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiReferenceList
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointerOfType
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
@@ -15,18 +21,52 @@ import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
import org.jetbrains.kotlin.light.classes.symbol.toPsiVisibilityForClass
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
internal abstract class SymbolLightInterfaceOrAnnotationClass(classOrObject: KtClassOrObject, ktModule: KtModule) :
SymbolLightClassForClassOrObject(classOrObject, ktModule) {
init {
require(isInterface || isAnnotation)
internal abstract class SymbolLightInterfaceOrAnnotationClass : SymbolLightClassForNamedClassOrObject {
constructor(
ktAnalysisSession: KtAnalysisSession,
ktModule: KtModule,
classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : super(
ktAnalysisSession = ktAnalysisSession,
ktModule = ktModule,
classOrObjectSymbol = classOrObjectSymbol,
manager = manager,
) {
val classKind = classOrObjectSymbol.classKind
require(classKind == KtClassKind.INTERFACE || classKind == KtClassKind.ANNOTATION_CLASS)
}
constructor(
classOrObject: KtClassOrObject,
ktModule: KtModule,
) : this(
classOrObjectDeclaration = classOrObject,
classOrObjectSymbolPointer = classOrObject.symbolPointerOfType(),
ktModule = ktModule,
manager = classOrObject.manager,
) {
require(classOrObject is KtClass && (classOrObject.isInterface() || classOrObject.isAnnotation()))
}
protected constructor(
classOrObjectDeclaration: KtClassOrObject?,
classOrObjectSymbolPointer: KtSymbolPointer<KtNamedClassOrObjectSymbol>,
ktModule: KtModule,
manager: PsiManager,
) : super(
classOrObjectDeclaration = classOrObjectDeclaration,
classOrObjectSymbolPointer = classOrObjectSymbolPointer,
ktModule = ktModule,
manager = manager,
)
private val _modifierList: PsiModifierList? by lazy {
val lazyModifiers = lazy {
withNamedClassOrObjectSymbol { classOrObjectSymbol ->
withClassOrObjectSymbol { classOrObjectSymbol ->
buildSet {
add(classOrObjectSymbol.toPsiVisibilityForClass(isNested = !isTopLevel))
add(PsiModifier.ABSTRACT)
@@ -38,7 +78,7 @@ internal abstract class SymbolLightInterfaceOrAnnotationClass(classOrObject: KtC
}
val lazyAnnotations = lazyPub {
withNamedClassOrObjectSymbol { classOrObjectSymbol ->
withClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.computeAnnotations(
parent = this@SymbolLightInterfaceOrAnnotationClass,
nullability = NullabilityType.Unknown,
@@ -56,9 +96,11 @@ internal abstract class SymbolLightInterfaceOrAnnotationClass(classOrObject: KtC
override fun getModifierList(): PsiModifierList? = _modifierList
private val _ownFields: List<KtLightField> by lazyPub {
mutableListOf<KtLightField>().also {
addCompanionObjectFieldIfNeeded(it)
addFieldsFromCompanionIfNeeded(it)
withClassOrObjectSymbol { classOrObjectSymbol ->
buildList {
addCompanionObjectFieldIfNeeded(this, classOrObjectSymbol)
addFieldsFromCompanionIfNeeded(this, classOrObjectSymbol)
}
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.light.classes.symbol.classes
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiReferenceList
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
@@ -50,16 +51,44 @@ import java.util.*
internal fun createSymbolLightClassNoCache(classOrObject: KtClassOrObject, ktModule: KtModule): KtLightClass? = when {
classOrObject.isObjectLiteral() -> SymbolLightAnonymousClass(classOrObject, ktModule)
classOrObject is KtEnumEntry -> lightClassForEnumEntry(classOrObject)
classOrObject.hasModifier(INLINE_KEYWORD) -> SymbolLightInlineClass(classOrObject, ktModule)
else -> createLightClassNoCache(classOrObject, ktModule)
}
internal fun createLightClassNoCache(ktClassOrObject: KtClassOrObject, ktModule: KtModule): SymbolLightClassBase = when {
ktClassOrObject.hasModifier(INLINE_KEYWORD) -> SymbolLightInlineClass(ktClassOrObject, ktModule)
ktClassOrObject is KtClass && ktClassOrObject.isAnnotation() -> SymbolLightAnnotationClass(ktClassOrObject, ktModule)
ktClassOrObject is KtClass && ktClassOrObject.isInterface() -> SymbolLightInterfaceClass(ktClassOrObject, ktModule)
else -> SymbolLightClass(ktClassOrObject, ktModule)
}
context(ktAnalysisSession@KtAnalysisSession)
internal fun createLightClassNoCache(
ktClassOrObjectSymbol: KtNamedClassOrObjectSymbol,
ktModule: KtModule,
manager: PsiManager,
): SymbolLightClassBase = when (ktClassOrObjectSymbol.classKind) {
KtClassKind.INTERFACE -> SymbolLightInterfaceClass(
ktAnalysisSession = this@ktAnalysisSession,
ktModule = ktModule,
classOrObjectSymbol = ktClassOrObjectSymbol,
manager = manager,
)
KtClassKind.ANNOTATION_CLASS -> SymbolLightAnnotationClass(
ktAnalysisSession = this@ktAnalysisSession,
ktModule = ktModule,
classOrObjectSymbol = ktClassOrObjectSymbol,
manager = manager,
)
else -> SymbolLightClass(
ktAnalysisSession = this@ktAnalysisSession,
ktModule = ktModule,
classOrObjectSymbol = ktClassOrObjectSymbol,
manager = manager,
)
}
private fun lightClassForEnumEntry(ktEnumEntry: KtEnumEntry): KtLightClass? {
if (ktEnumEntry.body == null) return null
@@ -72,7 +101,7 @@ private fun lightClassForEnumEntry(ktEnumEntry: KtEnumEntry): KtLightClass? {
}
context(ktAnalysisSession@KtAnalysisSession)
internal fun SymbolLightClassForClassOrObject.createConstructors(
internal fun SymbolLightClassForClassOrObject<*>.createConstructors(
declarations: Sequence<KtConstructorSymbol>,
result: MutableList<KtLightMethod>,
) {
@@ -129,26 +158,28 @@ private fun SymbolLightClassBase.shouldGenerateNoArgOverload(
!primaryConstructor.hasJvmOverloadsAnnotation()
}
private fun SymbolLightClassForClassOrObject.defaultConstructor(): KtLightMethod {
private fun SymbolLightClassForClassOrObject<*>.defaultConstructor(): KtLightMethod {
val classOrObject = kotlinOrigin
val visibility = when {
classOrObject is KtObjectDeclaration || isEnum -> PsiModifier.PRIVATE
classOrObject.hasModifier(SEALED_KEYWORD) -> PsiModifier.PROTECTED
classOrObject is KtEnumEntry -> PsiModifier.PACKAGE_LOCAL
isObject || isEnum -> PsiModifier.PRIVATE
classOrObject?.hasModifier(SEALED_KEYWORD) == true -> PsiModifier.PROTECTED
this is SymbolLightClassForEnumEntry -> PsiModifier.PACKAGE_LOCAL
else -> PsiModifier.PUBLIC
}
return noArgConstructor(visibility, METHOD_INDEX_FOR_DEFAULT_CTOR)
}
private fun SymbolLightClassForClassOrObject.noArgConstructor(
private fun SymbolLightClassForClassOrObject<*>.noArgConstructor(
visibility: String,
methodIndex: Int,
): KtLightMethod = SymbolLightNoArgConstructor(
LightMemberOriginForDeclaration(
originalElement = kotlinOrigin,
originKind = JvmDeclarationOriginKind.OTHER,
),
kotlinOrigin?.let {
LightMemberOriginForDeclaration(
originalElement = it,
originKind = JvmDeclarationOriginKind.OTHER,
)
},
this,
visibility,
methodIndex,
@@ -350,14 +381,17 @@ internal fun SymbolLightClassBase.createField(
}
context(KtAnalysisSession)
internal fun SymbolLightClassForClassOrObject.createInheritanceList(forExtendsList: Boolean, superTypes: List<KtType>): PsiReferenceList {
internal fun SymbolLightClassForClassOrObject<*>.createInheritanceList(
forExtendsList: Boolean,
superTypes: List<KtType>,
): PsiReferenceList {
val role = if (forExtendsList) PsiReferenceList.Role.EXTENDS_LIST else PsiReferenceList.Role.IMPLEMENTS_LIST
val listBuilder = KotlinSuperTypeListBuilder(
kotlinOrigin = kotlinOrigin.getSuperTypeList(),
kotlinOrigin = kotlinOrigin?.getSuperTypeList(),
manager = manager,
language = language,
role = role
role = role,
)
fun KtType.needToAddTypeIntoList(): Boolean {
@@ -404,8 +438,9 @@ internal fun SymbolLightClassForClassOrObject.createInheritanceList(forExtendsLi
context(KtAnalysisSession)
internal fun KtSymbolWithMembers.createInnerClasses(
manager: PsiManager,
containingClass: SymbolLightClassBase,
classOrObject: KtClassOrObject
classOrObject: KtClassOrObject?
): List<SymbolLightClassBase> {
val result = ArrayList<SymbolLightClassBase>()
@@ -414,16 +449,23 @@ internal fun KtSymbolWithMembers.createInnerClasses(
// we can't prohibit creating light classes with null names either since they can contain members
getDeclaredMemberScope().getClassifierSymbols().filterIsInstance<KtNamedClassOrObjectSymbol>().mapTo(result) {
createLightClassNoCache(it.psi(), ktModule = containingClass.ktModule)
val classOrObjectDeclaration = it.psiSafe<KtClassOrObject>()
if (classOrObjectDeclaration != null) {
createLightClassNoCache(classOrObjectDeclaration, containingClass.ktModule)
} else {
createLightClassNoCache(it, ktModule = containingClass.ktModule, manager)
}
}
val jvmDefaultMode =
classOrObject.getKtModuleOfTypeSafe<KtSourceModule>()?.languageVersionSettings?.getFlag(JvmAnalysisFlags.jvmDefaultMode)
?: JvmDefaultMode.DEFAULT
val jvmDefaultMode = classOrObject
?.getKtModuleOfTypeSafe<KtSourceModule>()
?.languageVersionSettings
?.getFlag(JvmAnalysisFlags.jvmDefaultMode)
?: JvmDefaultMode.DEFAULT
if (classOrObject.hasInterfaceDefaultImpls &&
jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE &&
containingClass is SymbolLightInterfaceClass
if (containingClass is SymbolLightInterfaceClass &&
classOrObject?.hasInterfaceDefaultImpls == true &&
jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE
) {
result.add(SymbolLightClassForInterfaceDefaultImpls(containingClass))
}
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.light.classes.symbol.fields
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
@@ -26,8 +25,7 @@ internal class SymbolLightFieldForEnumEntry(
private val enumEntry: KtEnumEntry,
private val enumEntryName: String,
containingClass: SymbolLightClass,
override val lightMemberOrigin: LightMemberOrigin?,
) : SymbolLightField(containingClass, lightMemberOrigin), PsiEnumConstant {
) : SymbolLightField(containingClass = containingClass, lightMemberOrigin = null), PsiEnumConstant {
internal fun <T> withEnumEntrySymbol(action: KtAnalysisSession.(KtEnumEntrySymbol) -> T): T = analyzeForLightClasses(ktModule) {
action(enumEntry.getEnumEntrySymbol())
}
@@ -12,29 +12,40 @@ import com.intellij.psi.PsiType
import org.jetbrains.annotations.NotNull
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.analysis.api.symbols.sourcePsiSafe
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.light.classes.symbol.analyzeForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.*
import org.jetbrains.kotlin.light.classes.symbol.annotations.SymbolLightSimpleAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasDeprecatedAnnotation
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForClassOrObject
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList
import org.jetbrains.kotlin.light.classes.symbol.nonExistentType
import org.jetbrains.kotlin.light.classes.symbol.toPsiVisibilityForMember
import org.jetbrains.kotlin.psi.KtObjectDeclaration
internal class SymbolLightFieldForObject(
private val objectDeclaration: KtObjectDeclaration,
containingClass: SymbolLightClassForClassOrObject,
internal class SymbolLightFieldForObject private constructor(
containingClass: SymbolLightClassForClassOrObject<*>,
private val name: String,
lightMemberOrigin: LightMemberOrigin?,
private val objectSymbolPointer: KtSymbolPointer<KtNamedClassOrObjectSymbol>,
override val kotlinOrigin: KtObjectDeclaration?,
) : SymbolLightField(containingClass, lightMemberOrigin) {
private fun <T> withObjectDeclarationSymbol(action: KtAnalysisSession.(KtNamedClassOrObjectSymbol) -> T): T =
analyzeForLightClasses(ktModule) {
action(requireNotNull(objectDeclaration.getNamedClassOrObjectSymbol()))
}
internal constructor(
ktAnalysisSession: KtAnalysisSession,
objectSymbol: KtNamedClassOrObjectSymbol,
name: String,
lightMemberOrigin: LightMemberOrigin?,
containingClass: SymbolLightClassForClassOrObject<*>,
) : this(
containingClass = containingClass,
name = name,
lightMemberOrigin = lightMemberOrigin,
kotlinOrigin = objectSymbol.sourcePsiSafe(),
objectSymbolPointer = with(ktAnalysisSession) { objectSymbol.createPointer() },
)
override val kotlinOrigin: KtObjectDeclaration = objectDeclaration
private fun <T> withObjectDeclarationSymbol(action: KtAnalysisSession.(KtNamedClassOrObjectSymbol) -> T): T =
objectSymbolPointer.withSymbol(ktModule, action)
override fun getName(): String = name
@@ -73,10 +84,19 @@ internal class SymbolLightFieldForObject(
override fun getInitializer(): PsiExpression? = null //TODO
override fun equals(other: Any?): Boolean =
this === other || other is SymbolLightFieldForObject && objectDeclaration == other.objectDeclaration
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is SymbolLightFieldForObject || other.ktModule != ktModule) return false
if (kotlinOrigin != null) {
return other.kotlinOrigin == kotlinOrigin
}
override fun hashCode(): Int = objectDeclaration.hashCode()
return other.kotlinOrigin == null &&
other.containingClass == containingClass &&
compareSymbolPointers(ktModule, other.objectSymbolPointer, objectSymbolPointer)
}
override fun isValid(): Boolean = objectDeclaration.isValid
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isValid(): Boolean = kotlinOrigin?.isValid ?: objectSymbolPointer.isValid(ktModule)
}
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMember
import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightParameterList
internal class SymbolLightNoArgConstructor(
lightMemberOrigin: LightMemberOrigin,
containingClass: SymbolLightClassForClassOrObject,
lightMemberOrigin: LightMemberOrigin?,
containingClass: SymbolLightClassForClassOrObject<*>,
private val visibility: String,
methodIndex: Int,
) : SymbolLightMethodBase(lightMemberOrigin, containingClass, methodIndex) {