[FIR IDE] LC Add anonymous objects support
+minor fixes
This commit is contained in:
@@ -103,6 +103,8 @@ abstract class KtAnalysisSession(override val token: ValidityToken) : ValidityTo
|
||||
|
||||
fun KtProperty.getVariableSymbol(): KtVariableSymbol = symbolProvider.getVariableSymbol(this)
|
||||
|
||||
fun KtObjectLiteralExpression.getAnonymousObjectSymbol(): KtAnonymousObjectSymbol = symbolProvider.getAnonymousObjectSymbol(this)
|
||||
|
||||
fun KtClassOrObject.getClassOrObjectSymbol(): KtClassOrObjectSymbol = symbolProvider.getClassOrObjectSymbol(this)
|
||||
|
||||
fun KtPropertyAccessor.getPropertyAccessorSymbol(): KtPropertyAccessorSymbol = symbolProvider.getPropertyAccessorSymbol(this)
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.frontend.api.symbols
|
||||
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithDeclarations
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
|
||||
abstract class KtAnonymousObjectSymbol : KtSymbolWithKind, KtAnnotatedSymbol, KtSymbolWithDeclarations {
|
||||
abstract val superTypes: List<KtType>
|
||||
|
||||
abstract override fun createPointer(): KtSymbolPointer<KtAnonymousObjectSymbol>
|
||||
}
|
||||
+5
-1
@@ -21,7 +21,10 @@ abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
|
||||
is KtEnumEntry -> getEnumEntrySymbol(psi)
|
||||
is KtLambdaExpression -> getAnonymousFunctionSymbol(psi)
|
||||
is KtProperty -> getVariableSymbol(psi)
|
||||
is KtClassOrObject -> getClassOrObjectSymbol(psi)
|
||||
is KtClassOrObject -> {
|
||||
val literalExpression = (psi as? KtObjectDeclaration)?.parent as? KtObjectLiteralExpression
|
||||
literalExpression?.let(::getAnonymousObjectSymbol) ?: getClassOrObjectSymbol(psi)
|
||||
}
|
||||
is KtPropertyAccessor -> getPropertyAccessorSymbol(psi)
|
||||
else -> error("Cannot build symbol for ${psi::class}")
|
||||
}
|
||||
@@ -35,6 +38,7 @@ abstract class KtSymbolProvider : KtAnalysisSessionComponent() {
|
||||
abstract fun getAnonymousFunctionSymbol(psi: KtNamedFunction): KtAnonymousFunctionSymbol
|
||||
abstract fun getAnonymousFunctionSymbol(psi: KtLambdaExpression): KtAnonymousFunctionSymbol
|
||||
abstract fun getVariableSymbol(psi: KtProperty): KtVariableSymbol
|
||||
abstract fun getAnonymousObjectSymbol(psi: KtObjectLiteralExpression): KtAnonymousObjectSymbol
|
||||
abstract fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol
|
||||
abstract fun getPropertyAccessorSymbol(psi: KtPropertyAccessor): KtPropertyAccessorSymbol
|
||||
|
||||
|
||||
+2
@@ -59,6 +59,8 @@ abstract class KtPropertySymbol : KtVariableSymbol(),
|
||||
|
||||
abstract val isOverride: Boolean
|
||||
|
||||
abstract val initializer: KtConstantValue?
|
||||
|
||||
abstract override fun createPointer(): KtSymbolPointer<KtPropertySymbol>
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||
@@ -106,7 +107,10 @@ internal class FirModuleResolveStateImpl(
|
||||
firLazyDeclarationResolver.lazyResolveDeclaration(container, cache, FirResolvePhase.BODY_RESOLVE, checkPCE = false /*TODO*/)
|
||||
}
|
||||
val firDeclaration = FirElementFinder.findElementIn<FirDeclaration>(container) { firDeclaration ->
|
||||
firDeclaration.psi == ktDeclaration
|
||||
when (val realPsi = firDeclaration.realPsi) {
|
||||
is KtObjectLiteralExpression -> realPsi.objectDeclaration == ktDeclaration
|
||||
else -> realPsi == ktDeclaration
|
||||
}
|
||||
}
|
||||
return firDeclaration
|
||||
?: error("FirDeclaration was not found for\n${ktDeclaration.getElementTextInContext()}")
|
||||
|
||||
+1
-35
@@ -7,10 +7,8 @@ package org.jetbrains.kotlin.idea.asJava
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiImplUtil
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.asJava.classes.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
|
||||
import org.jetbrains.kotlin.psi.KtCallElement
|
||||
|
||||
internal class FirLightAnnotationForAnnotationCall(
|
||||
@@ -46,36 +44,4 @@ internal class FirLightAnnotationForAnnotationCall(
|
||||
|
||||
override fun isEquivalentTo(another: PsiElement?): Boolean =
|
||||
basicIsEquivalentTo(this, another as? PsiAnnotation)
|
||||
}
|
||||
|
||||
private fun escapeString(str: String): String = buildString {
|
||||
str.forEach { char ->
|
||||
val escaped = when (char) {
|
||||
'\n' -> "\\n"
|
||||
'\r' -> "\\r"
|
||||
'\t' -> "\\t"
|
||||
'\"' -> "\\\""
|
||||
'\\' -> "\\\\"
|
||||
else -> "$char"
|
||||
}
|
||||
append(escaped)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtSimpleConstantValue<*>.asStringForPsiLiteral(parent: PsiElement): String =
|
||||
when (val value = this.constant) {
|
||||
is String -> "\"${escapeString(value)}\""
|
||||
is Long -> "${value}L"
|
||||
is Float -> "${value}f"
|
||||
else -> value?.toString() ?: "null"
|
||||
}
|
||||
|
||||
internal fun KtSimpleConstantValue<*>.createPsiLiteral(parent: PsiElement): PsiExpression? {
|
||||
val asString = asStringForPsiLiteral(parent)
|
||||
val instance = PsiElementFactory.getInstance(parent.project)
|
||||
return try {
|
||||
instance.createExpressionFromText(asString, parent)
|
||||
} catch (_: IncorrectOperationException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
-8
@@ -10,20 +10,14 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirAnnotationCall
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.mapAnnotationParameters
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget?): Boolean =
|
||||
@@ -42,8 +36,6 @@ internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(annotationUseSiteTarget:
|
||||
}
|
||||
|
||||
internal fun KtAnnotatedSymbol.isHiddenByDeprecation(annotationUseSiteTarget: AnnotationUseSiteTarget?): Boolean {
|
||||
|
||||
//TODO Move it to HL API
|
||||
require(this is KtFirSymbol<*>)
|
||||
|
||||
return this.firRef.withFir(FirResolvePhase.TYPES) {
|
||||
|
||||
+2
-3
@@ -31,16 +31,15 @@ internal class FirLightAnnotationClassSymbol(
|
||||
override fun isAnnotationType(): Boolean = true
|
||||
|
||||
private val _ownFields: List<KtLightField> by lazyPub {
|
||||
//TODO
|
||||
mutableListOf<KtLightField>().also {
|
||||
it.addCompanionObjectFieldIfNeeded()
|
||||
addCompanionObjectFieldIfNeeded(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getOwnFields(): List<KtLightField> = _ownFields
|
||||
|
||||
private val _ownMethods: List<KtLightMethod> by lazyPub {
|
||||
//TODO
|
||||
|
||||
val result = mutableListOf<KtLightMethod>()
|
||||
|
||||
analyzeWithSymbolAsContext(classOrObjectSymbol) {
|
||||
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.asJava.classes
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.InheritanceImplUtil
|
||||
import com.intellij.psi.impl.PsiClassImplUtil
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.stubs.IStubElementType
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
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.idea.asJava.FirLightClassBase
|
||||
import org.jetbrains.kotlin.idea.asJava.FirLightClassForSymbol
|
||||
import org.jetbrains.kotlin.idea.asJava.FirLightField
|
||||
import org.jetbrains.kotlin.idea.asJava.hasJvmFieldAnnotation
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtAnonymousObjectSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.debugText.getDebugText
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
|
||||
|
||||
internal class FirLightAnonymousClassForSymbol(
|
||||
private val anonymousObjectSymbol: KtAnonymousObjectSymbol,
|
||||
manager: PsiManager
|
||||
) : FirLightClassBase(manager),
|
||||
StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>>, PsiAnonymousClass {
|
||||
|
||||
private val _baseClassType: PsiClassType by lazyPub {
|
||||
extendsListTypes.firstOrNull()
|
||||
?: implementsListTypes.firstOrNull()
|
||||
?: PsiType.getJavaLangObject(manager, resolveScope)
|
||||
}
|
||||
|
||||
override fun getBaseClassReference(): PsiJavaCodeReferenceElement =
|
||||
JavaPsiFacade.getElementFactory(manager.project).createReferenceElementByType(baseClassType)
|
||||
|
||||
override fun getBaseClassType(): PsiClassType = _baseClassType
|
||||
|
||||
private val _extendsList by lazyPub { createInheritanceList(forExtendsList = true, anonymousObjectSymbol.superTypes) }
|
||||
private val _implementsList by lazyPub { createInheritanceList(forExtendsList = false, anonymousObjectSymbol.superTypes) }
|
||||
|
||||
override fun getExtendsList(): PsiReferenceList? = _extendsList
|
||||
override fun getImplementsList(): PsiReferenceList? = _implementsList
|
||||
|
||||
override fun getOwnFields(): List<KtLightField> = _ownFields
|
||||
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
|
||||
|
||||
|
||||
private val _ownMethods: List<KtLightMethod> by lazyPub {
|
||||
|
||||
val result = mutableListOf<KtLightMethod>()
|
||||
|
||||
analyzeWithSymbolAsContext(anonymousObjectSymbol) {
|
||||
val callableSymbols = anonymousObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
|
||||
createMethods(callableSymbols, isTopLevel = false, result)
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
private val _ownFields: List<KtLightField> by lazyPub {
|
||||
val result = mutableListOf<KtLightField>()
|
||||
val nameGenerator = FirLightField.FieldNameGenerator()
|
||||
|
||||
analyzeWithSymbolAsContext(anonymousObjectSymbol) {
|
||||
anonymousObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
|
||||
.filterIsInstance<KtPropertySymbol>()
|
||||
.forEach { propertySymbol ->
|
||||
createField(
|
||||
propertySymbol,
|
||||
nameGenerator,
|
||||
isTopLevel = false,
|
||||
forceStatic = false,
|
||||
takePropertyVisibility = propertySymbol.hasJvmFieldAnnotation(),
|
||||
result
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
private val _ownInnerClasses: List<FirLightClassForSymbol> by lazyPub {
|
||||
anonymousObjectSymbol.createInnerClasses(manager)
|
||||
}
|
||||
|
||||
override fun getOwnInnerClasses(): List<PsiClass> = _ownInnerClasses
|
||||
|
||||
override fun getScope(): PsiElement? = parent
|
||||
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
|
||||
override fun getSuperClass(): PsiClass? = PsiClassImplUtil.getSuperClass(this)
|
||||
override fun getSupers(): Array<PsiClass> = PsiClassImplUtil.getSupers(this)
|
||||
override fun getSuperTypes(): Array<PsiClassType> = PsiClassImplUtil.getSuperTypes(this)
|
||||
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean =
|
||||
InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
|
||||
|
||||
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean =
|
||||
baseClass?.let { InheritanceImplUtil.isInheritorDeep(this, it, classToByPass) } ?: false
|
||||
|
||||
override val kotlinOrigin: KtClassOrObject? = anonymousObjectSymbol.psi as? KtClassOrObject
|
||||
|
||||
override val originKind: LightClassOriginKind
|
||||
get() = LightClassOriginKind.SOURCE
|
||||
|
||||
override fun getArgumentList(): PsiExpressionList? = null
|
||||
override fun isInQualifiedNew(): Boolean = false
|
||||
override fun getName(): String? = null
|
||||
override fun getNameIdentifier(): KtLightIdentifier? = null
|
||||
override fun getModifierList(): PsiModifierList? = null
|
||||
override fun hasModifierProperty(name: String): Boolean = name == PsiModifier.FINAL
|
||||
override fun getContainingClass(): PsiClass? = null
|
||||
override fun isDeprecated(): Boolean = false //TODO
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
|
||||
override fun isInterface() = false
|
||||
override fun isAnnotationType() = false
|
||||
override fun getTypeParameterList(): PsiTypeParameterList? = null
|
||||
override fun getQualifiedName(): String? = null
|
||||
override fun isEnum() = false
|
||||
override fun getUseScope(): SearchScope = kotlinOrigin?.useScope ?: TODO()
|
||||
override fun getElementType(): IStubElementType<out StubElement<*>, *>? = kotlinOrigin?.elementType
|
||||
override fun getStub(): KotlinClassOrObjectStub<out KtClassOrObject>? = kotlinOrigin?.stub
|
||||
|
||||
override fun isEquivalentTo(another: PsiElement?): Boolean = equals(another) //TODO
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
this === other ||
|
||||
(other is FirLightAnonymousClassForSymbol && anonymousObjectSymbol == other.anonymousObjectSymbol)
|
||||
|
||||
override fun hashCode(): Int = anonymousObjectSymbol.hashCode()
|
||||
|
||||
override fun copy() =
|
||||
FirLightAnonymousClassForSymbol(anonymousObjectSymbol, manager)
|
||||
|
||||
override fun toString() =
|
||||
"${this::class.java.simpleName}:${kotlinOrigin?.getDebugText()}"
|
||||
}
|
||||
+11
-44
@@ -13,18 +13,15 @@ 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.asJava.classes.KotlinSuperTypeListBuilder
|
||||
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.getOrCreateFirLightClass
|
||||
import org.jetbrains.kotlin.idea.asJava.elements.FirLightTypeParameterListForSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.idea.util.ifFalse
|
||||
import org.jetbrains.kotlin.idea.util.ifTrue
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
@@ -61,7 +58,6 @@ internal abstract class FirLightClassForClassOrObjectSymbol(
|
||||
abstract override fun getExtendsList(): PsiReferenceList?
|
||||
abstract override fun getImplementsList(): PsiReferenceList?
|
||||
|
||||
|
||||
private val _typeParameterList: PsiTypeParameterList? by lazyPub {
|
||||
hasTypeParameters().ifTrue {
|
||||
val shiftCount = classOrObjectSymbol.isInner.ifTrue {
|
||||
@@ -90,45 +86,16 @@ internal abstract class FirLightClassForClassOrObjectSymbol(
|
||||
override fun isWritable() = false
|
||||
override val kotlinOrigin: KtClassOrObject? = classOrObjectSymbol.psi as? KtClassOrObject
|
||||
|
||||
protected fun createInheritanceList(forExtendsList: Boolean): PsiReferenceList {
|
||||
|
||||
val role = if (forExtendsList) PsiReferenceList.Role.EXTENDS_LIST else PsiReferenceList.Role.IMPLEMENTS_LIST
|
||||
|
||||
val listBuilder = KotlinSuperTypeListBuilder(
|
||||
kotlinOrigin = kotlinOrigin?.getSuperTypeList(),
|
||||
manager = manager,
|
||||
language = language,
|
||||
role = role
|
||||
)
|
||||
|
||||
fun KtType.needToAddTypeIntoList(): Boolean {
|
||||
if (this !is KtClassType) return false
|
||||
|
||||
// Do not add redundant "extends java.lang.Object" anywhere
|
||||
if (this.classId == StandardClassIds.Any) return false
|
||||
|
||||
// We don't have Enum among enums supertype in sources neither we do for decompiled class-files and light-classes
|
||||
if (isEnum && this.classId == StandardClassIds.Enum) return false
|
||||
|
||||
val isInterfaceType =
|
||||
(this.classSymbol as? KtClassOrObjectSymbol)?.classKind == KtClassKind.INTERFACE
|
||||
|
||||
return forExtendsList == !isInterfaceType
|
||||
}
|
||||
|
||||
//TODO Add support for kotlin.collections.
|
||||
classOrObjectSymbol.superTypes
|
||||
.filterIsInstance<KtClassType>()
|
||||
.filter { it.needToAddTypeIntoList() }
|
||||
.mapNotNull { it.mapSupertype(this, kotlinCollectionAsIs = true) }
|
||||
.forEach { listBuilder.addReference(it) }
|
||||
|
||||
return listBuilder
|
||||
}
|
||||
|
||||
protected fun MutableList<KtLightField>.addCompanionObjectFieldIfNeeded() {
|
||||
protected fun addCompanionObjectFieldIfNeeded(result: MutableList<KtLightField>) {
|
||||
classOrObjectSymbol.companionObject?.run {
|
||||
add(FirLightFieldForObjectSymbol(this, this@FirLightClassForClassOrObjectSymbol, null))
|
||||
result.add(
|
||||
FirLightFieldForObjectSymbol(
|
||||
objectSymbol = this,
|
||||
containingClass = this@FirLightClassForClassOrObjectSymbol,
|
||||
name = name.asString(),
|
||||
lightMemberOrigin = null
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +120,7 @@ internal abstract class FirLightClassForClassOrObjectSymbol(
|
||||
|
||||
abstract override fun hashCode(): Int
|
||||
|
||||
override fun getName(): String = classOrObjectSymbol.name.asString()
|
||||
override fun getName(): String? = classOrObjectSymbol.name.asString()
|
||||
|
||||
override fun hasModifierProperty(@NonNls name: String): Boolean = modifierList?.hasModifierProperty(name) ?: false
|
||||
|
||||
|
||||
+19
-7
@@ -21,10 +21,11 @@ import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.createFields
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.createField
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.createMethods
|
||||
import org.jetbrains.kotlin.idea.frontend.api.analyze
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -97,7 +98,7 @@ class FirLightClassForFacade(
|
||||
|
||||
private fun loadFieldsFromFile(
|
||||
file: KtFile,
|
||||
usedFieldNames: MutableSet<String>,
|
||||
nameGenerator: FirLightField.FieldNameGenerator,
|
||||
result: MutableList<KtLightField>
|
||||
) {
|
||||
val properties = file.declarations
|
||||
@@ -108,20 +109,31 @@ class FirLightClassForFacade(
|
||||
|
||||
if (properties.isEmpty()) return
|
||||
|
||||
val symbols = analyze(file) {
|
||||
val propertySymbols = analyze(file) {
|
||||
properties.mapNotNull {
|
||||
it.getSymbol() as? KtCallableSymbol
|
||||
it.getSymbol() as? KtPropertySymbol
|
||||
}
|
||||
}
|
||||
|
||||
createFields(symbols.asSequence(), usedFieldNames, isTopLevel = true, result)
|
||||
for (propertySymbol in propertySymbols) {
|
||||
val forceStaticAndPropertyVisibility = propertySymbol.hasJvmStaticAnnotation()
|
||||
createField(
|
||||
propertySymbol,
|
||||
nameGenerator,
|
||||
isTopLevel = true,
|
||||
forceStatic = forceStaticAndPropertyVisibility,
|
||||
takePropertyVisibility = forceStaticAndPropertyVisibility,
|
||||
result
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val _ownFields: List<KtLightField> by lazyPub {
|
||||
val result = mutableListOf<KtLightField>()
|
||||
val usedFieldNames = mutableSetOf<String>()
|
||||
val nameGenerator = FirLightField.FieldNameGenerator()
|
||||
for (file in files) {
|
||||
loadFieldsFromFile(file, usedFieldNames, result)
|
||||
loadFieldsFromFile(file, nameGenerator, result)
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
+80
-35
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_FOR_DEFAULT_CTOR
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.createFields
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.*
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.createInheritanceList
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.createInnerClasses
|
||||
import org.jetbrains.kotlin.idea.asJava.classes.createMethods
|
||||
import org.jetbrains.kotlin.idea.asJava.fields.FirLightFieldForEnumEntry
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
@@ -19,7 +21,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
|
||||
|
||||
internal class FirLightClassForSymbol(
|
||||
internal open class FirLightClassForSymbol(
|
||||
private val classOrObjectSymbol: KtClassOrObjectSymbol,
|
||||
manager: PsiManager
|
||||
) : FirLightClassForClassOrObjectSymbol(classOrObjectSymbol, manager) {
|
||||
@@ -73,28 +75,14 @@ internal class FirLightClassForSymbol(
|
||||
override fun getExtendsList(): PsiReferenceList? = _extendsList
|
||||
override fun getImplementsList(): PsiReferenceList? = _implementsList
|
||||
|
||||
override fun getOwnInnerClasses(): List<PsiClass> {
|
||||
val result = ArrayList<PsiClass>()
|
||||
|
||||
// workaround for ClassInnerStuffCache not supporting classes with null names, see KT-13927
|
||||
// inner classes with null names can't be searched for and can't be used from java anyway
|
||||
// we can't prohibit creating light classes with null names either since they can contain members
|
||||
|
||||
analyzeWithSymbolAsContext(classOrObjectSymbol) {
|
||||
classOrObjectSymbol.getDeclaredMemberScope().getAllSymbols().filterIsInstance<KtClassOrObjectSymbol>().mapTo(result) {
|
||||
FirLightClassForSymbol(it, manager)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
//if (classOrObject.hasInterfaceDefaultImpls) {
|
||||
// result.add(KtLightClassForInterfaceDefaultImpls(classOrObject))
|
||||
//}
|
||||
return result
|
||||
private val _ownInnerClasses: List<FirLightClassForSymbol> by lazyPub {
|
||||
classOrObjectSymbol.createInnerClasses(manager)
|
||||
}
|
||||
|
||||
private val _extendsList by lazyPub { createInheritanceList(forExtendsList = true) }
|
||||
private val _implementsList by lazyPub { createInheritanceList(forExtendsList = false) }
|
||||
override fun getOwnInnerClasses(): List<PsiClass> = _ownInnerClasses
|
||||
|
||||
private val _extendsList by lazyPub { createInheritanceList(forExtendsList = true, classOrObjectSymbol.superTypes) }
|
||||
private val _implementsList by lazyPub { createInheritanceList(forExtendsList = false, classOrObjectSymbol.superTypes) }
|
||||
|
||||
private val _ownMethods: List<KtLightMethod> by lazyPub {
|
||||
|
||||
@@ -106,6 +94,10 @@ internal class FirLightClassForSymbol(
|
||||
filterNot { function ->
|
||||
function is KtFunctionSymbol && function.name.asString().let { it == "values" || it == "valueOf" }
|
||||
}
|
||||
}.applyIf(classOrObjectSymbol.classKind == KtClassKind.OBJECT) {
|
||||
filterNot {
|
||||
it is KtPropertySymbol && it.isConst
|
||||
}
|
||||
}
|
||||
|
||||
createMethods(visibleDeclarations, isTopLevel = false, result)
|
||||
@@ -127,14 +119,7 @@ internal class FirLightClassForSymbol(
|
||||
result
|
||||
}
|
||||
|
||||
private val _ownFields: List<KtLightField> by lazyPub {
|
||||
|
||||
val result = mutableListOf<KtLightField>()
|
||||
|
||||
result.addCompanionObjectFieldIfNeeded()
|
||||
|
||||
val usedNames = mutableSetOf<String>()
|
||||
|
||||
private fun addFieldsFromCompanionIfNeeded(result: MutableList<KtLightField>, nameGenerator: FirLightField.FieldNameGenerator) {
|
||||
classOrObjectSymbol.companionObject?.run {
|
||||
analyzeWithSymbolAsContext(this) {
|
||||
getDeclaredMemberScope().getCallableSymbols()
|
||||
@@ -143,36 +128,96 @@ internal class FirLightClassForSymbol(
|
||||
.mapTo(result) {
|
||||
FirLightFieldForPropertySymbol(
|
||||
propertySymbol = it,
|
||||
usedNames = usedNames,
|
||||
nameGenerator = nameGenerator,
|
||||
containingClass = this@FirLightClassForSymbol,
|
||||
lightMemberOrigin = null,
|
||||
isTopLevel = false,
|
||||
forceStatic = true
|
||||
forceStatic = true,
|
||||
takePropertyVisibility = true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun addObjectFields(result: MutableList<KtLightField>, nameGenerator: FirLightField.FieldNameGenerator) {
|
||||
analyzeWithSymbolAsContext(classOrObjectSymbol) {
|
||||
classOrObjectSymbol.getDeclaredMemberScope().getAllSymbols()
|
||||
.filterIsInstance<KtClassOrObjectSymbol>()
|
||||
.filter { it.classKind == KtClassKind.OBJECT }
|
||||
.mapTo(result) {
|
||||
FirLightFieldForObjectSymbol(
|
||||
objectSymbol = it,
|
||||
containingClass = this@FirLightClassForSymbol,
|
||||
name = nameGenerator.generateUniqueFieldName(it.name.asString()),
|
||||
lightMemberOrigin = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addInstanceFieldIfNeeded(result: MutableList<KtLightField>) {
|
||||
val isNamedObject = classOrObjectSymbol.classKind == KtClassKind.OBJECT
|
||||
if (isNamedObject && classOrObjectSymbol.symbolKind != KtSymbolKind.LOCAL) {
|
||||
result.add(FirLightFieldForObjectSymbol(classOrObjectSymbol, this@FirLightClassForSymbol, null))
|
||||
result.add(
|
||||
FirLightFieldForObjectSymbol(
|
||||
objectSymbol = classOrObjectSymbol,
|
||||
containingClass = this@FirLightClassForSymbol,
|
||||
name = "INSTANCE",
|
||||
lightMemberOrigin = null
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addPropertyBackingFields(result: MutableList<KtLightField>, nameGenerator: FirLightField.FieldNameGenerator) {
|
||||
analyzeWithSymbolAsContext(classOrObjectSymbol) {
|
||||
val propertySymbols = classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
|
||||
.filterIsInstance<KtPropertySymbol>()
|
||||
.applyIf(classOrObjectSymbol.classKind == KtClassKind.COMPANION_OBJECT) {
|
||||
filterNot { it.hasJvmFieldAnnotation() || it.isConst }
|
||||
}
|
||||
createFields(propertySymbols, usedNames, isTopLevel = false, result)
|
||||
|
||||
val isObject = classOrObjectSymbol.classKind == KtClassKind.OBJECT
|
||||
|
||||
for (propertySymbol in propertySymbols) {
|
||||
val isJvmStatic = propertySymbol.hasJvmStaticAnnotation()
|
||||
val forceStatic = isObject || isJvmStatic
|
||||
val takePropertyVisibility = (isObject && propertySymbol.isConst) || isJvmStatic
|
||||
|
||||
createField(
|
||||
declaration = propertySymbol,
|
||||
nameGenerator = nameGenerator,
|
||||
isTopLevel = false,
|
||||
forceStatic = forceStatic,
|
||||
takePropertyVisibility = takePropertyVisibility,
|
||||
result = result
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (isEnum) {
|
||||
classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
|
||||
.filterIsInstance<KtEnumEntrySymbol>()
|
||||
.mapTo(result) { FirLightFieldForEnumEntry(it, this@FirLightClassForSymbol, null) }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private val _ownFields: List<KtLightField> by lazyPub {
|
||||
|
||||
val result = mutableListOf<KtLightField>()
|
||||
|
||||
addCompanionObjectFieldIfNeeded(result)
|
||||
addInstanceFieldIfNeeded(result)
|
||||
|
||||
val nameGenerator = FirLightField.FieldNameGenerator()
|
||||
|
||||
addObjectFields(result, nameGenerator)
|
||||
addFieldsFromCompanionIfNeeded(result, nameGenerator)
|
||||
addPropertyBackingFields(result, nameGenerator)
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ internal class FirLightInterfaceClassSymbol(
|
||||
|
||||
private val _ownFields: List<KtLightField> by lazyPub {
|
||||
mutableListOf<KtLightField>().also {
|
||||
it.addCompanionObjectFieldIfNeeded()
|
||||
addCompanionObjectFieldIfNeeded(it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ internal class FirLightInterfaceClassSymbol(
|
||||
FirLightInterfaceClassSymbol(classOrObjectSymbol, manager)
|
||||
|
||||
private val _extendsList: PsiReferenceList by lazyPub {
|
||||
createInheritanceList(forExtendsList = false)
|
||||
createInheritanceList(forExtendsList = false, classOrObjectSymbol.superTypes)
|
||||
}
|
||||
|
||||
override fun getExtendsList(): PsiReferenceList? = _extendsList
|
||||
|
||||
+5
-1
@@ -18,7 +18,11 @@ internal abstract class FirLightInterfaceOrAnnotationClassSymbol(
|
||||
) : FirLightClassForClassOrObjectSymbol(classOrObjectSymbol, manager) {
|
||||
|
||||
init {
|
||||
require(classOrObjectSymbol.classKind == KtClassKind.INTERFACE || classOrObjectSymbol.classKind == KtClassKind.ANNOTATION_CLASS)
|
||||
require(
|
||||
classOrObjectSymbol.classKind == KtClassKind.OBJECT ||
|
||||
classOrObjectSymbol.classKind == KtClassKind.INTERFACE ||
|
||||
classOrObjectSymbol.classKind == KtClassKind.ANNOTATION_CLASS
|
||||
)
|
||||
}
|
||||
|
||||
private val _modifierList: PsiModifierList? by lazyPub {
|
||||
|
||||
+88
-20
@@ -5,29 +5,33 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.asJava.classes
|
||||
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.PsiReferenceList
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
|
||||
import org.jetbrains.kotlin.asJava.classes.KotlinSuperTypeListBuilder
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_BASE
|
||||
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.idea.asJava.*
|
||||
import org.jetbrains.kotlin.idea.asJava.fields.FirLightFieldForEnumEntry
|
||||
import org.jetbrains.kotlin.idea.frontend.api.analyze
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtCommonSymbolModality
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithDeclarations
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
|
||||
import java.util.*
|
||||
|
||||
fun getOrCreateFirLightClass(classOrObject: KtClassOrObject): KtLightClass? =
|
||||
@@ -53,10 +57,17 @@ fun createFirLightClassNoCache(classOrObject: KtClassOrObject): KtLightClass? {
|
||||
return null
|
||||
}
|
||||
|
||||
val anonymousObject = classOrObject.parent as? KtObjectLiteralExpression
|
||||
if (anonymousObject != null) {
|
||||
return analyze(anonymousObject) {
|
||||
FirLightAnonymousClassForSymbol(anonymousObject.getAnonymousObjectSymbol(), anonymousObject.manager)
|
||||
}
|
||||
}
|
||||
|
||||
return when {
|
||||
classOrObject is KtEnumEntry -> lightClassForEnumEntry(classOrObject)
|
||||
classOrObject.isObjectLiteral() -> return null //TODO
|
||||
classOrObject.hasModifier(KtTokens.INLINE_KEYWORD) -> return null //TODO
|
||||
|
||||
else -> {
|
||||
analyze(classOrObject) {
|
||||
val symbol = classOrObject.getClassOrObjectSymbol()
|
||||
@@ -192,10 +203,12 @@ internal fun FirLightClassBase.createMethods(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun FirLightClassBase.createFields(
|
||||
declarations: Sequence<KtCallableSymbol>,
|
||||
usedNames: MutableSet<String>,
|
||||
internal fun FirLightClassBase.createField(
|
||||
declaration: KtPropertySymbol,
|
||||
nameGenerator: FirLightField.FieldNameGenerator,
|
||||
isTopLevel: Boolean,
|
||||
forceStatic: Boolean,
|
||||
takePropertyVisibility: Boolean,
|
||||
result: MutableList<KtLightField>
|
||||
) {
|
||||
fun hasBackingField(property: KtPropertySymbol): Boolean {
|
||||
@@ -207,18 +220,73 @@ internal fun FirLightClassBase.createFields(
|
||||
return property.hasBackingField
|
||||
}
|
||||
|
||||
for (declaration in declarations) {
|
||||
if (declaration !is KtPropertySymbol) continue
|
||||
if (!hasBackingField(declaration)) continue
|
||||
if (!hasBackingField(declaration)) return
|
||||
|
||||
result.add(
|
||||
FirLightFieldForPropertySymbol(
|
||||
propertySymbol = declaration,
|
||||
usedNames = usedNames,
|
||||
containingClass = this@createFields,
|
||||
lightMemberOrigin = null,
|
||||
isTopLevel = isTopLevel
|
||||
)
|
||||
result.add(
|
||||
FirLightFieldForPropertySymbol(
|
||||
propertySymbol = declaration,
|
||||
nameGenerator = nameGenerator,
|
||||
containingClass = this,
|
||||
lightMemberOrigin = null,
|
||||
isTopLevel = isTopLevel,
|
||||
forceStatic = forceStatic,
|
||||
takePropertyVisibility = takePropertyVisibility
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
internal fun FirLightClassBase.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(),
|
||||
manager = manager,
|
||||
language = language,
|
||||
role = role
|
||||
)
|
||||
|
||||
fun KtType.needToAddTypeIntoList(): Boolean {
|
||||
if (this !is KtClassType) return false
|
||||
|
||||
// Do not add redundant "extends java.lang.Object" anywhere
|
||||
if (this.classId == StandardClassIds.Any) return false
|
||||
|
||||
// We don't have Enum among enums supertype in sources neither we do for decompiled class-files and light-classes
|
||||
if (isEnum && this.classId == StandardClassIds.Enum) return false
|
||||
|
||||
val isInterfaceType =
|
||||
(this.classSymbol as? KtClassOrObjectSymbol)?.classKind == KtClassKind.INTERFACE
|
||||
|
||||
return forExtendsList == !isInterfaceType
|
||||
}
|
||||
|
||||
//TODO Add support for kotlin.collections.
|
||||
superTypes
|
||||
.filterIsInstance<KtClassType>()
|
||||
.filter { it.needToAddTypeIntoList() }
|
||||
.mapNotNull { it.mapSupertype(this, kotlinCollectionAsIs = true) }
|
||||
.forEach { listBuilder.addReference(it) }
|
||||
|
||||
return listBuilder
|
||||
}
|
||||
|
||||
internal fun KtSymbolWithDeclarations.createInnerClasses(manager: PsiManager): List<FirLightClassForSymbol> {
|
||||
val result = ArrayList<FirLightClassForSymbol>()
|
||||
|
||||
// workaround for ClassInnerStuffCache not supporting classes with null names, see KT-13927
|
||||
// inner classes with null names can't be searched for and can't be used from java anyway
|
||||
// we can't prohibit creating light classes with null names either since they can contain members
|
||||
|
||||
analyzeWithSymbolAsContext(this) {
|
||||
getDeclaredMemberScope().getAllSymbols().filterIsInstance<KtClassOrObjectSymbol>().mapTo(result) {
|
||||
FirLightClassForSymbol(it, manager)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
//if (classOrObject.hasInterfaceDefaultImpls) {
|
||||
// result.add(KtLightClassForInterfaceDefaultImpls(classOrObject))
|
||||
//}
|
||||
return result
|
||||
}
|
||||
@@ -80,4 +80,18 @@ internal abstract class FirLightField protected constructor(
|
||||
visitor.visitElement(this)
|
||||
}
|
||||
}
|
||||
|
||||
internal class FieldNameGenerator {
|
||||
private val usedNames: MutableSet<String> = mutableSetOf()
|
||||
|
||||
fun generateUniqueFieldName(base: String): String {
|
||||
if (usedNames.add(base)) return base
|
||||
var i = 1
|
||||
while (true) {
|
||||
val suggestion = "$base$$i"
|
||||
if (usedNames.add(suggestion)) return suggestion
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -18,13 +18,13 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
internal class FirLightFieldForObjectSymbol(
|
||||
private val objectSymbol: KtClassOrObjectSymbol,
|
||||
containingClass: KtLightClass,
|
||||
private val name: String,
|
||||
lightMemberOrigin: LightMemberOrigin?,
|
||||
) : FirLightField(containingClass, lightMemberOrigin) {
|
||||
|
||||
override val kotlinOrigin: KtDeclaration? = objectSymbol.psi as? KtDeclaration
|
||||
|
||||
private val _name = if (objectSymbol.classKind == KtClassKind.COMPANION_OBJECT) objectSymbol.name.asString() else "INSTANCE"
|
||||
override fun getName(): String = _name
|
||||
override fun getName(): String = name
|
||||
|
||||
private val _modifierList: PsiModifierList by lazyPub {
|
||||
val modifiers = setOf(objectSymbol.computeVisibility(isTopLevel = false), PsiModifier.STATIC, PsiModifier.FINAL)
|
||||
@@ -58,8 +58,8 @@ internal class FirLightFieldForObjectSymbol(
|
||||
override fun equals(other: Any?): Boolean =
|
||||
this === other ||
|
||||
(other is FirLightFieldForObjectSymbol &&
|
||||
kotlinOrigin == other.kotlinOrigin &&
|
||||
objectSymbol == other.objectSymbol)
|
||||
kotlinOrigin == other.kotlinOrigin &&
|
||||
objectSymbol == other.objectSymbol)
|
||||
|
||||
override fun hashCode(): Int = kotlinOrigin.hashCode()
|
||||
}
|
||||
+11
-19
@@ -12,18 +12,20 @@ import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
|
||||
internal class FirLightFieldForPropertySymbol(
|
||||
private val propertySymbol: KtPropertySymbol,
|
||||
usedNames: MutableSet<String>,
|
||||
nameGenerator: FieldNameGenerator,
|
||||
containingClass: FirLightClassBase,
|
||||
lightMemberOrigin: LightMemberOrigin?,
|
||||
isTopLevel: Boolean,
|
||||
forceStatic: Boolean = false
|
||||
forceStatic: Boolean,
|
||||
takePropertyVisibility: Boolean
|
||||
) : FirLightField(containingClass, lightMemberOrigin) {
|
||||
|
||||
private val _name: String = generateUniqueFieldName(usedNames, propertySymbol.name.asString())
|
||||
private val _name: String = nameGenerator.generateUniqueFieldName(propertySymbol.name.asString())
|
||||
|
||||
override val kotlinOrigin: KtDeclaration? = propertySymbol.psi as? KtDeclaration
|
||||
|
||||
@@ -53,7 +55,6 @@ internal class FirLightFieldForPropertySymbol(
|
||||
|
||||
private val _modifierList: PsiModifierList by lazyPub {
|
||||
|
||||
val isJvmField = propertySymbol.hasJvmFieldAnnotation()
|
||||
val suppressFinal = !propertySymbol.isVal
|
||||
|
||||
val modifiersFromSymbol = propertySymbol.computeModalityForMethod(
|
||||
@@ -67,7 +68,7 @@ internal class FirLightFieldForPropertySymbol(
|
||||
)
|
||||
|
||||
val visibility =
|
||||
if (isJvmField) propertySymbol.computeVisibility(isTopLevel = false) else PsiModifier.PRIVATE
|
||||
if (takePropertyVisibility) propertySymbol.computeVisibility(isTopLevel = false) else PsiModifier.PRIVATE
|
||||
|
||||
val modifiersWithVisibility = basicModifiers + visibility
|
||||
|
||||
@@ -95,10 +96,13 @@ internal class FirLightFieldForPropertySymbol(
|
||||
FirLightClassModifierList(this, modifiers, annotations)
|
||||
}
|
||||
|
||||
override fun getModifierList(): PsiModifierList? = _modifierList
|
||||
override fun getModifierList(): PsiModifierList = _modifierList
|
||||
|
||||
private val _initializer by lazyPub {
|
||||
(propertySymbol.initializer as? KtSimpleConstantValue<*>)?.createPsiLiteral(this)
|
||||
}
|
||||
|
||||
override fun getInitializer(): PsiExpression? = null //TODO
|
||||
override fun getInitializer(): PsiExpression? = _initializer
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
this === other ||
|
||||
@@ -107,16 +111,4 @@ internal class FirLightFieldForPropertySymbol(
|
||||
propertySymbol == other.propertySymbol)
|
||||
|
||||
override fun hashCode(): Int = kotlinOrigin.hashCode()
|
||||
|
||||
companion object {
|
||||
private fun generateUniqueFieldName(usedNames: MutableSet<String>, base: String): String {
|
||||
if (usedNames.add(base)) return base
|
||||
var i = 1
|
||||
while (true) {
|
||||
val suggestion = "$base$$i"
|
||||
if (usedNames.add(suggestion)) return suggestion
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,24 +10,24 @@ import com.intellij.psi.impl.cache.TypeInfo
|
||||
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||
import com.intellij.psi.impl.compiled.SignatureParsing
|
||||
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMember
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer.isSupertypeOf
|
||||
import org.jetbrains.kotlin.fir.backend.jvm.jvmTypeMapper
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.isPrimitiveNumberOrUnsignedNumberType
|
||||
import org.jetbrains.kotlin.fir.isPrimitiveType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.typeCheckerContext
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirClassType
|
||||
@@ -37,10 +37,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.*
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.typeConstructor
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import java.text.StringCharacterIterator
|
||||
|
||||
internal fun <L : Any> L.invalidAccess(): Nothing =
|
||||
@@ -60,9 +57,8 @@ internal fun KtType.asPsiType(
|
||||
): PsiType {
|
||||
require(this is KtFirType)
|
||||
require(context is KtFirSymbol<*>)
|
||||
|
||||
val session = context.firRef.withFir(phase) { it.session }
|
||||
return coneType.asPsiType(session, TypeMappingMode.DEFAULT, parent)
|
||||
return coneType.asPsiType(session, context.firRef.resolveState, TypeMappingMode.DEFAULT, parent)
|
||||
}
|
||||
|
||||
internal fun KtClassOrObjectSymbol.typeForClassSymbol(psiElement: PsiElement): PsiType {
|
||||
@@ -74,33 +70,53 @@ internal fun KtClassOrObjectSymbol.typeForClassSymbol(psiElement: PsiElement): P
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
return type.asPsiType(session, TypeMappingMode.DEFAULT, psiElement)
|
||||
return type.asPsiType(session, this.firRef.resolveState, TypeMappingMode.DEFAULT, psiElement)
|
||||
}
|
||||
|
||||
private class AnonymousTypesSubstitutor(private val session: FirSession, private val state: FirModuleResolveState) :
|
||||
AbstractConeSubstitutor() {
|
||||
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||
|
||||
if (type !is ConeClassLikeType) return null
|
||||
|
||||
val isAnonymous = type.classId.let { it?.shortClassName?.asString() == SpecialNames.ANONYMOUS }
|
||||
if (!isAnonymous) return null
|
||||
|
||||
val firstSuperType = (type.lookupTag.toSymbol(session) as? FirClassSymbol)?.fir
|
||||
?.withFirDeclaration(state, FirResolvePhase.SUPER_TYPES) {
|
||||
(it as? FirClass)?.superConeTypes?.firstOrNull()
|
||||
}
|
||||
|
||||
if (firstSuperType != null) return firstSuperType
|
||||
|
||||
return if (type.nullability.isNullable) session.builtinTypes.nullableAnyType.type
|
||||
else session.builtinTypes.anyType.type
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun ConeKotlinType.asPsiType(
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState,
|
||||
mode: TypeMappingMode,
|
||||
psiContext: PsiElement,
|
||||
): PsiType {
|
||||
|
||||
if (this is ConeClassErrorType || this !is SimpleTypeMarker) return psiContext.nonExistentType()
|
||||
if (this.typeArguments.any { it is ConeClassErrorType }) return psiContext.nonExistentType()
|
||||
if (this is ConeClassLikeType) {
|
||||
val classId = classId
|
||||
//TODO make anonymous type deriving
|
||||
if (classId != null && classId.shortClassName.asString() == SpecialNames.ANONYMOUS) return PsiType.NULL
|
||||
}
|
||||
|
||||
val correctedType = AnonymousTypesSubstitutor(session, state).substituteOrSelf(this)
|
||||
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
|
||||
//TODO Check thread safety
|
||||
session.jvmTypeMapper.mapType(this, mode, signatureWriter)
|
||||
session.jvmTypeMapper.mapType(correctedType, mode, signatureWriter)
|
||||
|
||||
val canonicalSignature = signatureWriter.toString()
|
||||
|
||||
if (canonicalSignature.contains("L<error>")) return psiContext.nonExistentType()
|
||||
//TODO Fix it in typemapper
|
||||
val patchedCanonicalSignature = canonicalSignature.replace(SpecialNames.ANONYMOUS, "java.lang.Object")
|
||||
val signature = StringCharacterIterator(patchedCanonicalSignature)
|
||||
require(!canonicalSignature.contains(SpecialNames.ANONYMOUS))
|
||||
|
||||
val signature = StringCharacterIterator(canonicalSignature)
|
||||
val javaType = SignatureParsing.parseTypeString(signature, StubBuildingVisitor.GUESSING_MAPPER)
|
||||
val typeInfo = TypeInfo.fromString(javaType, false)
|
||||
val typeText = TypeInfo.createTypeText(typeInfo) ?: return psiContext.nonExistentType()
|
||||
@@ -109,9 +125,16 @@ private fun ConeKotlinType.asPsiType(
|
||||
return typeElement.type
|
||||
}
|
||||
|
||||
private fun mapSupertype(psiContext: PsiElement, session: FirSession, supertype: ConeKotlinType, kotlinCollectionAsIs: Boolean = false) =
|
||||
private fun mapSupertype(
|
||||
psiContext: PsiElement,
|
||||
session: FirSession,
|
||||
firResolvePhase: FirModuleResolveState,
|
||||
supertype: ConeKotlinType,
|
||||
kotlinCollectionAsIs: Boolean = false
|
||||
) =
|
||||
supertype.asPsiType(
|
||||
session,
|
||||
firResolvePhase,
|
||||
if (kotlinCollectionAsIs) TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS else TypeMappingMode.SUPER_TYPE,
|
||||
psiContext
|
||||
) as? PsiClassType
|
||||
@@ -129,6 +152,7 @@ internal fun KtClassType.mapSupertype(
|
||||
return mapSupertype(
|
||||
psiContext,
|
||||
session,
|
||||
contextSymbol.firRef.resolveState,
|
||||
this.coneType,
|
||||
kotlinCollectionAsIs,
|
||||
)
|
||||
@@ -280,6 +304,39 @@ internal fun KtType.getTypeNullability(context: KtSymbol, phase: FirResolvePhase
|
||||
return if (isNotPrimitiveType) NullabilityType.NotNull else NullabilityType.Unknown
|
||||
}
|
||||
|
||||
|
||||
private fun escapeString(str: String): String = buildString {
|
||||
str.forEach { char ->
|
||||
val escaped = when (char) {
|
||||
'\n' -> "\\n"
|
||||
'\r' -> "\\r"
|
||||
'\t' -> "\\t"
|
||||
'\"' -> "\\\""
|
||||
'\\' -> "\\\\"
|
||||
else -> "$char"
|
||||
}
|
||||
append(escaped)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtSimpleConstantValue<*>.asStringForPsiLiteral(): String =
|
||||
when (val value = this.constant) {
|
||||
is String -> "\"${escapeString(value)}\""
|
||||
is Long -> "${value}L"
|
||||
is Float -> "${value}f"
|
||||
else -> value?.toString() ?: "null"
|
||||
}
|
||||
|
||||
internal fun KtSimpleConstantValue<*>.createPsiLiteral(parent: PsiElement): PsiExpression? {
|
||||
val asString = asStringForPsiLiteral()
|
||||
val instance = PsiElementFactory.getInstance(parent.project)
|
||||
return try {
|
||||
instance.createExpressionFromText(asString, parent)
|
||||
} catch (_: IncorrectOperationException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> Set<T>.add(what: T, `if`: Boolean): Set<T> =
|
||||
applyIf(`if`) { this + what }
|
||||
|
||||
|
||||
+6
-1
@@ -87,6 +87,7 @@ internal class KtSymbolByFirBuilder private constructor(
|
||||
is FirField -> buildFieldSymbol(fir)
|
||||
is FirAnonymousFunction -> buildAnonymousFunctionSymbol(fir)
|
||||
is FirPropertyAccessor -> buildPropertyAccessorSymbol(fir)
|
||||
is FirAnonymousObject -> buildAnonymousObjectSymbol(fir)
|
||||
else ->
|
||||
TODO(fir::class.toString())
|
||||
}
|
||||
@@ -111,6 +112,9 @@ internal class KtSymbolByFirBuilder private constructor(
|
||||
|
||||
fun buildClassSymbol(fir: FirRegularClass) = symbolsCache.cache(fir) { KtFirClassOrObjectSymbol(fir, resolveState, token, this) }
|
||||
|
||||
fun buildAnonymousObjectSymbol(fir: FirAnonymousObject) =
|
||||
symbolsCache.cache(fir) { KtFirAnonymousObjectSymbol(fir, resolveState, token, this) }
|
||||
|
||||
// TODO it can be a constructor parameter, which may be split into parameter & property
|
||||
// we should handle them both
|
||||
fun buildParameterSymbol(fir: FirValueParameter) =
|
||||
@@ -127,7 +131,8 @@ internal class KtSymbolByFirBuilder private constructor(
|
||||
}
|
||||
|
||||
fun buildConstructorSymbol(fir: FirConstructor) = symbolsCache.cache(fir) { KtFirConstructorSymbol(fir, resolveState, token, this) }
|
||||
fun buildTypeParameterSymbol(fir: FirTypeParameter) = symbolsCache.cache(fir) { KtFirTypeParameterSymbol(fir, resolveState, token, this) }
|
||||
fun buildTypeParameterSymbol(fir: FirTypeParameter) =
|
||||
symbolsCache.cache(fir) { KtFirTypeParameterSymbol(fir, resolveState, token, this) }
|
||||
|
||||
fun buildTypeAliasSymbol(fir: FirTypeAlias) = symbolsCache.cache(fir) { KtFirTypeAliasSymbol(fir, resolveState, token) }
|
||||
fun buildEnumEntrySymbol(fir: FirEnumEntry) = symbolsCache.cache(fir) { KtFirEnumEntrySymbol(fir, resolveState, token, this) }
|
||||
|
||||
+2
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.frontend.api.components.KtScopeProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirAnonymousObjectSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
|
||||
@@ -59,6 +60,7 @@ internal class KtFirScopeProvider(
|
||||
|
||||
private inline fun <T> KtSymbolWithDeclarations.withFirForScope(crossinline body: (FirClass<*>) -> T): T? = when (this) {
|
||||
is KtFirClassOrObjectSymbol -> firRef.withFir(FirResolvePhase.SUPER_TYPES, body)
|
||||
is KtFirAnonymousObjectSymbol -> firRef.withFir(FirResolvePhase.SUPER_TYPES, body)
|
||||
is KtFirEnumEntrySymbol -> firRef.withFir(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
|
||||
val initializer = it.initializer
|
||||
check(initializer is FirAnonymousObject)
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.frontend.api.fir.symbols
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.superConeTypes
|
||||
import org.jetbrains.kotlin.idea.fir.findPsi
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtAnonymousObjectSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
|
||||
internal class KtFirAnonymousObjectSymbol(
|
||||
fir: FirAnonymousObject,
|
||||
resolveState: FirModuleResolveState,
|
||||
override val token: ValidityToken,
|
||||
private val builder: KtSymbolByFirBuilder
|
||||
) : KtAnonymousObjectSymbol(), KtFirSymbol<FirAnonymousObject> {
|
||||
|
||||
override val firRef = firRef(fir, resolveState)
|
||||
override val symbolKind: KtSymbolKind = KtSymbolKind.LOCAL
|
||||
override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.session) }
|
||||
|
||||
override val annotations: List<KtAnnotationCall> by firRef.withFirAndCache(FirResolvePhase.TYPES) {
|
||||
convertAnnotation(it)
|
||||
}
|
||||
|
||||
override val superTypes: List<KtType> by firRef.withFirAndCache(FirResolvePhase.SUPER_TYPES) { fir ->
|
||||
fir.superConeTypes.map {
|
||||
builder.buildKtType(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createPointer(): KtSymbolPointer<KtAnonymousObjectSymbol> =
|
||||
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)
|
||||
?: throw CanNotCreateSymbolPointerForLocalLibraryDeclarationException("Cannot create pointer for KtFirAnonymousObjectSymbol")
|
||||
}
|
||||
+3
-5
@@ -15,14 +15,12 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.KtFirMemberPropertySymbolPointer
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignature
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertConstantExpression
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertyGetterSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySetterSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtCommonSymbolModality
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
|
||||
@@ -48,7 +46,7 @@ internal class KtFirPropertySymbol(
|
||||
override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
|
||||
override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) }
|
||||
override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
|
||||
|
||||
override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> fir.initializer?.convertConstantExpression() }
|
||||
override val symbolKind: KtSymbolKind
|
||||
get() = firRef.withFir { fir ->
|
||||
when (fir.containingClass()?.classId) {
|
||||
|
||||
+7
@@ -87,7 +87,14 @@ internal class KtFirSymbolProvider(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAnonymousObjectSymbol(psi: KtObjectLiteralExpression): KtAnonymousObjectSymbol = withValidityAssertion {
|
||||
psi.objectDeclaration.withFirDeclarationOfType<FirAnonymousObject, KtAnonymousObjectSymbol>(resolveState) {
|
||||
firSymbolBuilder.buildAnonymousObjectSymbol(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getClassOrObjectSymbol(psi: KtClassOrObject): KtClassOrObjectSymbol = withValidityAssertion {
|
||||
check(psi !is KtObjectDeclaration || psi.parent !is KtObjectLiteralExpression)
|
||||
psi.withFirDeclarationOfType<FirRegularClass, KtClassOrObjectSymbol>(resolveState) {
|
||||
firSymbolBuilder.buildClassSymbol(it)
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ internal fun mapAnnotationParameters(annotationCall: FirAnnotationCall, session:
|
||||
return resultSet
|
||||
}
|
||||
|
||||
private fun FirExpression.convertConstantExpression(): KtConstantValue =
|
||||
internal fun FirExpression.convertConstantExpression(): KtConstantValue =
|
||||
when (this) {
|
||||
is FirConstExpression<*> -> KtSimpleConstantValue(value)
|
||||
else -> KtUnsupportedConstantValue
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
class AnonymousContainer {
|
||||
val anonymousObject = object : Runnable {
|
||||
override fun run() {
|
||||
|
||||
}
|
||||
val data = 123
|
||||
}
|
||||
}
|
||||
|
||||
// SYMBOLS:
|
||||
/*
|
||||
KtFirFunctionSymbol:
|
||||
annotations: []
|
||||
callableIdIfNonLocal: <anonymous>.run
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: true
|
||||
isSuspend: false
|
||||
modality: FINAL
|
||||
name: run
|
||||
origin: SOURCE
|
||||
receiverType: null
|
||||
symbolKind: MEMBER
|
||||
type: kotlin/Unit
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: PUBLIC
|
||||
|
||||
KtFirPropertySymbol:
|
||||
annotations: []
|
||||
callableIdIfNonLocal: <anonymous>.data
|
||||
getter: KtFirPropertyGetterSymbol(<getter>)
|
||||
hasBackingField: true
|
||||
initializer: 123
|
||||
isConst: false
|
||||
isExtension: false
|
||||
isLateInit: false
|
||||
isOverride: false
|
||||
isVal: true
|
||||
modality: FINAL
|
||||
name: data
|
||||
origin: SOURCE
|
||||
receiverType: null
|
||||
setter: null
|
||||
symbolKind: MEMBER
|
||||
type: kotlin/Int
|
||||
visibility: PUBLIC
|
||||
|
||||
KtFirAnonymousObjectSymbol:
|
||||
annotations: []
|
||||
origin: SOURCE
|
||||
superTypes: [java/lang/Runnable]
|
||||
symbolKind: LOCAL
|
||||
|
||||
KtFirPropertySymbol:
|
||||
annotations: []
|
||||
callableIdIfNonLocal: AnonymousContainer.anonymousObject
|
||||
getter: KtFirPropertyGetterSymbol(<getter>)
|
||||
hasBackingField: true
|
||||
initializer: KtUnsupportedConstantValue
|
||||
isConst: false
|
||||
isExtension: false
|
||||
isLateInit: false
|
||||
isOverride: false
|
||||
isVal: true
|
||||
modality: FINAL
|
||||
name: anonymousObject
|
||||
origin: SOURCE
|
||||
receiverType: null
|
||||
setter: null
|
||||
symbolKind: MEMBER
|
||||
type: java/lang/Runnable
|
||||
visibility: PUBLIC
|
||||
|
||||
KtFirClassOrObjectSymbol:
|
||||
annotations: []
|
||||
classIdIfNonLocal: AnonymousContainer
|
||||
classKind: CLASS
|
||||
companionObject: null
|
||||
isInner: false
|
||||
modality: FINAL
|
||||
name: AnonymousContainer
|
||||
origin: SOURCE
|
||||
primaryConstructor: KtFirConstructorSymbol(<constructor>)
|
||||
superTypes: [kotlin/Any]
|
||||
symbolKind: TOP_LEVEL
|
||||
typeParameters: []
|
||||
visibility: PUBLIC
|
||||
*/
|
||||
+5
@@ -33,6 +33,11 @@ public class SymbolsByPsiBuildingTestGenerated extends AbstractSymbolsByPsiBuild
|
||||
runTest("idea/idea-frontend-fir/testData/symbolsByPsi/annotations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("anonymousObject.kt")
|
||||
public void testAnonymousObject() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/testData/symbolsByPsi/anonymousObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("class.kt")
|
||||
public void testClass() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/testData/symbolsByPsi/class.kt");
|
||||
|
||||
Reference in New Issue
Block a user