[FIR IDE] LC Add callable declarations to KtFileSymbol

This commit is contained in:
Igor Yakovlev
2020-12-11 21:11:41 +03:00
parent fb63b74b37
commit da54dbba8e
3 changed files with 40 additions and 49 deletions
@@ -9,5 +9,8 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
abstract class KtFileSymbol : KtAnnotatedSymbol { abstract class KtFileSymbol : KtAnnotatedSymbol {
abstract val topLevelCallableSymbols: List<KtCallableSymbol>
abstract override fun createPointer(): KtSymbolPointer<KtFileSymbol> abstract override fun createPointer(): KtSymbolPointer<KtFileSymbol>
} }
@@ -12,31 +12,26 @@ import com.intellij.psi.impl.light.LightEmptyImplementsList
import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.impl.light.LightModifierList
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.classes.* import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.asJava.elements.*
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass import org.jetbrains.kotlin.asJava.elements.*
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.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.asJava.classes.createField import org.jetbrains.kotlin.idea.asJava.classes.createField
import org.jetbrains.kotlin.idea.asJava.classes.createMethods import org.jetbrains.kotlin.idea.asJava.classes.createMethods
import org.jetbrains.kotlin.idea.frontend.api.analyze 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.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFileSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
class FirLightClassForFacade( class FirLightClassForFacade(
manager: PsiManager, manager: PsiManager,
@@ -80,32 +75,24 @@ class FirLightClassForFacade(
override fun getModifierList(): PsiModifierList = _modifierList override fun getModifierList(): PsiModifierList = _modifierList
override fun getScope(): PsiElement? = parent override fun getScope(): PsiElement = parent
private fun loadMethodsFromFile(
file: KtFile,
result: MutableList<KtLightMethod>
) {
val declarations = file.declarations
.filterIsInstance<KtNamedDeclaration>()
.filterNot { multiFileClass && it.isPrivate() }
if (declarations.isEmpty()) return
val symbols = analyze(file) {
declarations.mapNotNull {
it.getSymbol() as? KtCallableSymbol
}
}
createMethods(symbols.asSequence(), result, isTopLevel = true)
}
private val _ownMethods: List<KtLightMethod> by lazyPub { private val _ownMethods: List<KtLightMethod> by lazyPub {
val result = mutableListOf<KtLightMethod>() val result = mutableListOf<KtLightMethod>()
for (file in files) {
loadMethodsFromFile(file, result) val methodsAndProperties = sequence<KtCallableSymbol> {
for (fileSymbol in fileSymbols) {
for (callableSymbol in fileSymbol.topLevelCallableSymbols) {
if (callableSymbol !is KtFunctionSymbol && callableSymbol !is KtPropertySymbol) continue
if (callableSymbol !is KtSymbolWithVisibility) continue
val isPrivate = callableSymbol.toPsiVisibilityForMember(isTopLevel = true) == PsiModifier.PRIVATE
if (isPrivate && multiFileClass) continue
yield(callableSymbol)
}
}
} }
createMethods(methodsAndProperties, result, isTopLevel = true)
result result
} }
@@ -114,25 +101,16 @@ class FirLightClassForFacade(
} }
private fun loadFieldsFromFile( private fun loadFieldsFromFile(
file: KtFile, fileSymbol: KtFileSymbol,
nameGenerator: FirLightField.FieldNameGenerator, nameGenerator: FirLightField.FieldNameGenerator,
result: MutableList<KtLightField> result: MutableList<KtLightField>
) { ) {
val properties = file.declarations for (propertySymbol in fileSymbol.topLevelCallableSymbols) {
.filterIsInstance<KtProperty>()
.applyIf(multiFileClass) {
filter { it.hasModifier(KtTokens.CONST_KEYWORD) }
}
if (properties.isEmpty()) return if (propertySymbol !is KtPropertySymbol) continue
val propertySymbols = analyze(file) { if (propertySymbol is KtKotlinPropertySymbol && propertySymbol.isConst && multiFileClass) continue
properties.mapNotNull {
it.getSymbol() as? KtPropertySymbol
}
}
for (propertySymbol in propertySymbols) {
val isLateInitWithPublicAccessors = if (propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit) { val isLateInitWithPublicAccessors = if (propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit) {
val getterIsPublic = propertySymbol.getter?.toPsiVisibilityForMember(isTopLevel = true) val getterIsPublic = propertySymbol.getter?.toPsiVisibilityForMember(isTopLevel = true)
?.let { it == PsiModifier.PUBLIC } ?: true ?.let { it == PsiModifier.PUBLIC } ?: true
@@ -160,8 +138,8 @@ class FirLightClassForFacade(
private val _ownFields: List<KtLightField> by lazyPub { private val _ownFields: List<KtLightField> by lazyPub {
val result = mutableListOf<KtLightField>() val result = mutableListOf<KtLightField>()
val nameGenerator = FirLightField.FieldNameGenerator() val nameGenerator = FirLightField.FieldNameGenerator()
for (file in files) { for (fileSymbol in fileSymbols) {
loadFieldsFromFile(file, nameGenerator, result) loadFieldsFromFile(fileSymbol, nameGenerator, result)
} }
result result
} }
@@ -266,6 +244,8 @@ class FirLightClassForFacade(
if (this.hashCode() != other.hashCode()) return false if (this.hashCode() != other.hashCode()) return false
if (manager != other.manager) return false if (manager != other.manager) return false
if (facadeClassFqName != other.facadeClassFqName) return false if (facadeClassFqName != other.facadeClassFqName) return false
if (!fileSymbols.containsAll(other.fileSymbols)) return false
if (!other.fileSymbols.containsAll(fileSymbols)) return false
return true return true
} }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.symbols package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.fir.findPsi import org.jetbrains.kotlin.idea.fir.findPsi
@@ -14,6 +15,7 @@ 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.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation 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.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFileSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFileSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer
@@ -27,7 +29,13 @@ internal class KtFirFileSymbol(
) : KtFileSymbol(), KtFirSymbol<FirFile> { ) : KtFileSymbol(), KtFirSymbol<FirFile> {
override val firRef = firRef(fir, resolveState) override val firRef = firRef(fir, resolveState)
override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.session) } override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.session) }
override val topLevelCallableSymbols: List<KtCallableSymbol> by firRef.withFirAndCache {
it.declarations.mapNotNull { declaration ->
if (declaration is FirCallableDeclaration<*>) builder.buildCallableSymbol(declaration) else null
}
}
override fun createPointer(): KtSymbolPointer<KtFileSymbol> { override fun createPointer(): KtSymbolPointer<KtFileSymbol> {
KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it } KtPsiBasedSymbolPointer.createForSymbolFromSource(this)?.let { return it }