[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.descriptors.*
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.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.dispatchReceiverClassOrNull
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
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.ir.ObsoleteDescriptorBasedAPI
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.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addIfNotNull
class Fir2IrLazyClass(
components: Fir2IrComponents,
@@ -145,59 +144,51 @@ class Fir2IrLazyClass(
override val declarations: MutableList<IrDeclaration> by lazyVar(lock) {
val result = mutableListOf<IrDeclaration>()
val processedNames = mutableSetOf<Name>()
// NB: it's necessary to take all callables from scope,
// e.g. to avoid accessing un-enhanced Java declarations with FirJavaTypeRef etc. inside
val scope = fir.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
scope.processDeclaredConstructors {
result += declarationStorage.getIrConstructorSymbol(it).owner
}
for (declaration in fir.declarations) {
when (declaration) {
is FirSimpleFunction -> {
if (fir.classKind == ClassKind.ENUM_CLASS && declaration.isStatic &&
(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).
// For such members we currently can't tell whether they are compiler-generated methods or not.
result += declarationStorage.getIrFunctionSymbol(declaration.symbol).owner
} else if (declaration.name !in processedNames) {
processedNames += declaration.name
if (fir.classKind == ClassKind.ANNOTATION_CLASS && declaration.origin == FirDeclarationOrigin.Java) {
// Java annotation values are exposed as properties.
scope.processPropertiesByName(declaration.name) {
if (it is FirPropertySymbol && it.dispatchReceiverClassOrNull() == fir.symbol.toLookupTag()) {
result += declarationStorage.getIrPropertySymbol(it).owner as IrProperty
}
}
} else {
scope.processFunctionsByName(declaration.name) {
if (it.dispatchReceiverClassOrNull() == fir.symbol.toLookupTag()) {
if (it.isAbstractMethodOfAny()) {
return@processFunctionsByName
}
result += declarationStorage.getIrFunctionSymbol(it).owner
}
}
}
if (declaration is FirRegularClass) {
val nestedSymbol = classifierStorage.getIrClassSymbol(declaration.symbol)
result += nestedSymbol.owner
}
}
// Handle generated methods for enum classes (values(), valueOf(String)).
// TODO we also come here for all deserialized static enum members (with declaration.source == null).
// For such members we currently can't tell whether they are compiler-generated methods or not.
if (fir.classKind == ClassKind.ENUM_CLASS) {
for (declaration in fir.declarations) {
if (
declaration is FirSimpleFunction &&
declaration.isStatic &&
(declaration.source == null || declaration.source?.kind == KtFakeSourceElementKind.EnumGeneratedDeclaration)
) {
result += declarationStorage.getIrFunctionSymbol(declaration.symbol).owner
}
}
}
val ownerLookupTag = fir.symbol.toLookupTag()
for (name in scope.getCallableNames()) {
scope.processFunctionsByName(name) {
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) {
processedNames += declaration.name
scope.processPropertiesByName(declaration.name) {
if (it is FirPropertySymbol && it.dispatchReceiverClassOrNull() == fir.symbol.toLookupTag()) {
result += declarationStorage.getIrPropertySymbol(it).owner as IrProperty
}
}
}
}
scope.processPropertiesByName(name) {
if (it.isSubstitutionOrIntersectionOverride) return@processPropertiesByName
if (it is FirPropertySymbol && it.dispatchReceiverClassOrNull() == ownerLookupTag) {
result.addIfNotNull(declarationStorage.getIrPropertySymbol(it).owner as? IrDeclaration)
}
is FirRegularClass -> {
val nestedSymbol = classifierStorage.getIrClassSymbol(declaration.symbol)
result += nestedSymbol.owner
}
else -> continue
}
}
@@ -205,14 +196,6 @@ class Fir2IrLazyClass(
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
}