[FIR2IR] Fix collecting declarations for Fir2IrLazyClass

Existed code might lose declarations in two cases:
1. When there is a declared function which is mapped to property
    (java synthetic properties)
2. When class has property and function with same name
This commit is contained in:
Dmitriy Novozhilov
2021-10-25 15:22:15 +03:00
committed by teamcityserver
parent 307fa66dda
commit 33f78e3903
@@ -8,17 +8,15 @@ package org.jetbrains.kotlin.fir.lazy
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.isNullableAny import org.jetbrains.kotlin.fir.types.isNullableAny
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -31,6 +29,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addIfNotNull
class Fir2IrLazyClass( class Fir2IrLazyClass(
components: Fir2IrComponents, components: Fir2IrComponents,
@@ -145,59 +144,51 @@ class Fir2IrLazyClass(
override val declarations: MutableList<IrDeclaration> by lazyVar(lock) { override val declarations: MutableList<IrDeclaration> by lazyVar(lock) {
val result = mutableListOf<IrDeclaration>() val result = mutableListOf<IrDeclaration>()
val processedNames = mutableSetOf<Name>()
// NB: it's necessary to take all callables from scope, // NB: it's necessary to take all callables from scope,
// e.g. to avoid accessing un-enhanced Java declarations with FirJavaTypeRef etc. inside // e.g. to avoid accessing un-enhanced Java declarations with FirJavaTypeRef etc. inside
val scope = fir.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) val scope = fir.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processDeclaredConstructors { scope.processDeclaredConstructors {
result += declarationStorage.getIrConstructorSymbol(it).owner result += declarationStorage.getIrConstructorSymbol(it).owner
} }
for (declaration in fir.declarations) { for (declaration in fir.declarations) {
when (declaration) { if (declaration is FirRegularClass) {
is FirSimpleFunction -> { val nestedSymbol = classifierStorage.getIrClassSymbol(declaration.symbol)
if (fir.classKind == ClassKind.ENUM_CLASS && declaration.isStatic && result += nestedSymbol.owner
(declaration.source == null || declaration.source?.kind == KtFakeSourceElementKind.EnumGeneratedDeclaration) }
) { }
// Handle generated methods for enum classes (values(), valueOf(String)).
// TODO we also come here for all deserialized static enum members (with declaration.source == null). // Handle generated methods for enum classes (values(), valueOf(String)).
// For such members we currently can't tell whether they are compiler-generated methods or not. // TODO we also come here for all deserialized static enum members (with declaration.source == null).
result += declarationStorage.getIrFunctionSymbol(declaration.symbol).owner // For such members we currently can't tell whether they are compiler-generated methods or not.
} else if (declaration.name !in processedNames) { if (fir.classKind == ClassKind.ENUM_CLASS) {
processedNames += declaration.name for (declaration in fir.declarations) {
if (fir.classKind == ClassKind.ANNOTATION_CLASS && declaration.origin == FirDeclarationOrigin.Java) { if (
// Java annotation values are exposed as properties. declaration is FirSimpleFunction &&
scope.processPropertiesByName(declaration.name) { declaration.isStatic &&
if (it is FirPropertySymbol && it.dispatchReceiverClassOrNull() == fir.symbol.toLookupTag()) { (declaration.source == null || declaration.source?.kind == KtFakeSourceElementKind.EnumGeneratedDeclaration)
result += declarationStorage.getIrPropertySymbol(it).owner as IrProperty ) {
} result += declarationStorage.getIrFunctionSymbol(declaration.symbol).owner
} }
} else { }
scope.processFunctionsByName(declaration.name) { }
if (it.dispatchReceiverClassOrNull() == fir.symbol.toLookupTag()) {
if (it.isAbstractMethodOfAny()) { val ownerLookupTag = fir.symbol.toLookupTag()
return@processFunctionsByName for (name in scope.getCallableNames()) {
} scope.processFunctionsByName(name) {
result += declarationStorage.getIrFunctionSymbol(it).owner if (it.isSubstitutionOrIntersectionOverride) return@processFunctionsByName
} if (it.dispatchReceiverClassOrNull() == ownerLookupTag) {
} if (it.isAbstractMethodOfAny()) {
} return@processFunctionsByName
} }
result += declarationStorage.getIrFunctionSymbol(it).owner
} }
is FirProperty -> { }
if (declaration.name !in processedNames) { scope.processPropertiesByName(name) {
processedNames += declaration.name if (it.isSubstitutionOrIntersectionOverride) return@processPropertiesByName
scope.processPropertiesByName(declaration.name) { if (it is FirPropertySymbol && it.dispatchReceiverClassOrNull() == ownerLookupTag) {
if (it is FirPropertySymbol && it.dispatchReceiverClassOrNull() == fir.symbol.toLookupTag()) { result.addIfNotNull(declarationStorage.getIrPropertySymbol(it).owner as? IrDeclaration)
result += declarationStorage.getIrPropertySymbol(it).owner as IrProperty
}
}
}
} }
is FirRegularClass -> {
val nestedSymbol = classifierStorage.getIrClassSymbol(declaration.symbol)
result += nestedSymbol.owner
}
else -> continue
} }
} }
@@ -205,14 +196,6 @@ class Fir2IrLazyClass(
result += getFakeOverridesByName(name) result += getFakeOverridesByName(name)
} }
// TODO: remove this check to save time
// for (declaration in result) {
// if (declaration.parent != this) {
// throw AssertionError(
// "Unmatched parent for lazy class ${fir.name} member ${declaration.render()} f/o ${declaration.isFakeOverride}"
// )
// }
// }
result result
} }