[FIR IDE] LC Fix generating unique field names

This commit is contained in:
Igor Yakovlev
2020-11-24 00:05:51 +03:00
parent 18e5af37ff
commit 56c3faee00
5 changed files with 31 additions and 14 deletions
@@ -13,3 +13,5 @@ class A {
private val j: String = { "a" }() private val j: String = { "a" }()
private val j: String = { "b" }() private val j: String = { "b" }()
} }
// FIR_COMPARISON
@@ -114,6 +114,7 @@ class FirLightClassForFacade(
private fun loadFieldsFromFile( private fun loadFieldsFromFile(
file: KtFile, file: KtFile,
usedFieldNames: MutableSet<String>,
result: MutableList<KtLightField> result: MutableList<KtLightField>
) { ) {
@@ -130,13 +131,14 @@ class FirLightClassForFacade(
} }
} }
createFields(symbols.asSequence(), isTopLevel = true, result) createFields(symbols.asSequence(), usedFieldNames, isTopLevel = true, result)
} }
private val _ownFields: List<KtLightField> by lazyPub { private val _ownFields: List<KtLightField> by lazyPub {
val result = mutableListOf<KtLightField>() val result = mutableListOf<KtLightField>()
val usedFieldNames = mutableSetOf<String>()
for (file in files) { for (file in files) {
loadFieldsFromFile(file, result) loadFieldsFromFile(file, usedFieldNames, result)
} }
result result
} }
@@ -133,6 +133,8 @@ internal class FirLightClassForSymbol(
result.addCompanionObjectFieldIfNeeded() result.addCompanionObjectFieldIfNeeded()
val usedNames = mutableSetOf<String>()
classOrObjectSymbol.companionObject?.run { classOrObjectSymbol.companionObject?.run {
analyzeWithSymbolAsContext(this) { analyzeWithSymbolAsContext(this) {
getDeclaredMemberScope().getCallableSymbols() getDeclaredMemberScope().getCallableSymbols()
@@ -141,6 +143,7 @@ internal class FirLightClassForSymbol(
.mapTo(result) { .mapTo(result) {
FirLightFieldForPropertySymbol( FirLightFieldForPropertySymbol(
propertySymbol = it, propertySymbol = it,
usedNames = usedNames,
containingClass = this@FirLightClassForSymbol, containingClass = this@FirLightClassForSymbol,
lightMemberOrigin = null, lightMemberOrigin = null,
isTopLevel = false, isTopLevel = false,
@@ -161,7 +164,7 @@ internal class FirLightClassForSymbol(
.applyIf(classOrObjectSymbol.classKind == KtClassKind.COMPANION_OBJECT) { .applyIf(classOrObjectSymbol.classKind == KtClassKind.COMPANION_OBJECT) {
filterNot { it.hasJvmFieldAnnotation() || it.isConst } filterNot { it.hasJvmFieldAnnotation() || it.isConst }
} }
createFields(propertySymbols, isTopLevel = false, result) createFields(propertySymbols, usedNames, isTopLevel = false, result)
if (isEnum) { if (isEnum) {
classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols() classOrObjectSymbol.getDeclaredMemberScope().getCallableSymbols()
@@ -10,29 +10,24 @@ import com.intellij.psi.util.CachedValuesManager
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_BASE import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_BASE
import org.jetbrains.kotlin.asJava.classes.safeIsLocal
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod 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.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.asJava.* import org.jetbrains.kotlin.idea.asJava.*
import org.jetbrains.kotlin.idea.asJava.FirLightClassForSymbol
import org.jetbrains.kotlin.idea.asJava.fields.FirLightFieldForEnumEntry import org.jetbrains.kotlin.idea.asJava.fields.FirLightFieldForEnumEntry
import org.jetbrains.kotlin.idea.frontend.api.analyze import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.* 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.KtAnnotatedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtCommonSymbolModality 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.KtSymbolVisibility
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.* 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.psiUtil.containingClass import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.psi.psiUtil.isLambdaOutsideParentheses
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
import org.jetbrains.kotlin.util.containingNonLocalDeclaration
import java.util.* import java.util.*
fun getOrCreateFirLightClass(classOrObject: KtClassOrObject): KtLightClass? = fun getOrCreateFirLightClass(classOrObject: KtClassOrObject): KtLightClass? =
@@ -199,6 +194,7 @@ internal fun FirLightClassBase.createMethods(
internal fun FirLightClassBase.createFields( internal fun FirLightClassBase.createFields(
declarations: Sequence<KtCallableSymbol>, declarations: Sequence<KtCallableSymbol>,
usedNames: MutableSet<String>,
isTopLevel: Boolean, isTopLevel: Boolean,
result: MutableList<KtLightField> result: MutableList<KtLightField>
) { ) {
@@ -211,7 +207,6 @@ internal fun FirLightClassBase.createFields(
return property.hasBackingField return property.hasBackingField
} }
//TODO isHiddenByDeprecation
for (declaration in declarations) { for (declaration in declarations) {
if (declaration !is KtPropertySymbol) continue if (declaration !is KtPropertySymbol) continue
if (!hasBackingField(declaration)) continue if (!hasBackingField(declaration)) continue
@@ -219,6 +214,7 @@ internal fun FirLightClassBase.createFields(
result.add( result.add(
FirLightFieldForPropertySymbol( FirLightFieldForPropertySymbol(
propertySymbol = declaration, propertySymbol = declaration,
usedNames = usedNames,
containingClass = this@createFields, containingClass = this@createFields,
lightMemberOrigin = null, lightMemberOrigin = null,
isTopLevel = isTopLevel isTopLevel = isTopLevel
@@ -16,12 +16,15 @@ import org.jetbrains.kotlin.psi.KtDeclaration
internal class FirLightFieldForPropertySymbol( internal class FirLightFieldForPropertySymbol(
private val propertySymbol: KtPropertySymbol, private val propertySymbol: KtPropertySymbol,
usedNames: MutableSet<String>,
containingClass: FirLightClassBase, containingClass: FirLightClassBase,
lightMemberOrigin: LightMemberOrigin?, lightMemberOrigin: LightMemberOrigin?,
isTopLevel: Boolean, isTopLevel: Boolean,
forceStatic: Boolean = false forceStatic: Boolean = false
) : FirLightField(containingClass, lightMemberOrigin) { ) : FirLightField(containingClass, lightMemberOrigin) {
private val _name: String = generateUniqueFieldName(usedNames, propertySymbol.name.asString())
override val kotlinOrigin: KtDeclaration? = propertySymbol.psi as? KtDeclaration override val kotlinOrigin: KtDeclaration? = propertySymbol.psi as? KtDeclaration
private val _returnedType: PsiType by lazyPub { private val _returnedType: PsiType by lazyPub {
@@ -46,7 +49,6 @@ internal class FirLightFieldForPropertySymbol(
override fun getType(): PsiType = _returnedType override fun getType(): PsiType = _returnedType
private val _name = propertySymbol.name.asString()
override fun getName(): String = _name override fun getName(): String = _name
private val _modifierList: PsiModifierList by lazyPub { private val _modifierList: PsiModifierList by lazyPub {
@@ -105,4 +107,16 @@ internal class FirLightFieldForPropertySymbol(
propertySymbol == other.propertySymbol) propertySymbol == other.propertySymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode() 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++
}
}
}
} }