diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt index e97d1bd2a1c..da32ee74e24 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt @@ -242,7 +242,7 @@ internal object ConeTypeCompatibilityChecker { private fun FirTypeParameterSymbol?.collectUpperBounds(): Set { if (this == null) return emptySet() - return fir.bounds.flatMap { it.coneTypeSafe().collectUpperBounds() }.toSet() + return resolvedBounds.flatMap { it.coneTypeSafe().collectUpperBounds() }.toSet() } private fun ConeKotlinType?.collectLowerBounds(): Set { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 2ad529ed66b..bab35acaed6 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -17,17 +17,18 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock -import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike +import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.impl.multipleDelegatesWithTheSameSignature import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.lexer.KtModifierKeywordToken @@ -47,9 +48,9 @@ import org.jetbrains.kotlin.util.ImplementationStatus import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addToStdlib.safeAs -private val INLINE_ONLY_ANNOTATION_CLASS_ID = ClassId.topLevel(FqName("kotlin.internal.InlineOnly")) +private val INLINE_ONLY_ANNOTATION_CLASS_ID: ClassId = ClassId.topLevel(FqName("kotlin.internal.InlineOnly")) -fun FirClass.unsubstitutedScope(context: CheckerContext) = +fun FirClass.unsubstitutedScope(context: CheckerContext): FirTypeScope = this.unsubstitutedScope(context.sessionHolder.session, context.sessionHolder.scopeSession, withForcedTypeCalculator = false) /** @@ -121,32 +122,21 @@ fun FirTypeRef.toRegularClass(session: FirSession): FirRegularClass? { return coneType.toRegularClass(session) } -/** - * Returns FirSimpleFunction based on the given FirFunctionCall - */ -inline fun FirQualifiedAccessExpression.getDeclaration(): T? { - return this.calleeReference.safeAs() - ?.resolvedSymbol - ?.fir as? T -} - /** * Returns the ClassLikeDeclaration where the Fir object has been defined * or null if no proper declaration has been found. */ -fun FirDeclaration.getContainingClass(context: CheckerContext): FirClassLikeDeclaration? = - this.safeAs()?.containingClass()?.toSymbol(context.session)?.fir +fun FirDeclaration.getContainingClassSymbol(context: CheckerContext): FirClassLikeSymbol<*>? = + this.safeAs()?.containingClass()?.toSymbol(context.session) -fun FirClassLikeSymbol<*>.outerClass(context: CheckerContext): FirClassLikeSymbol<*>? { +fun FirBasedSymbol<*>.getContainingClassSymbol(context: CheckerContext): FirClassLikeSymbol<*>? = fir.getContainingClassSymbol(context) + +fun FirClassLikeSymbol<*>.outerClassSymbol(context: CheckerContext): FirClassLikeSymbol<*>? { if (this !is FirClassSymbol<*>) return null val outerClassId = classId.outerClassId ?: return null return context.session.symbolProvider.getClassLikeSymbolByFqName(outerClassId) } -fun FirClass.outerClass(context: CheckerContext): FirClass? { - return symbol.outerClass(context)?.fir as? FirClass -} - /** * Returns the FirClassLikeDeclaration that the * sequence of FirTypeAlias'es points to starting @@ -290,10 +280,10 @@ fun FirClass.findNonInterfaceSupertype(context: CheckerContext): FirTypeRef? { return null } -val FirFunctionCall.isIterator +val FirFunctionCall.isIterator: Boolean get() = this.calleeReference.name.asString() == "" -fun ConeKotlinType.isSubtypeOfThrowable(session: FirSession) = +fun ConeKotlinType.isSubtypeOfThrowable(session: FirSession): Boolean = session.builtinTypes.throwableType.type.isSupertypeOf(session.typeContext, this.fullyExpandedType(session)) val FirValueParameter.hasValOrVar: Boolean @@ -302,10 +292,10 @@ val FirValueParameter.hasValOrVar: Boolean return source.getChild(VAL_VAR_TOKEN_SET) != null } -fun KotlinTypeMarker.isSupertypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?) = +fun KotlinTypeMarker.isSupertypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?): Boolean = type != null && AbstractTypeChecker.isSubtypeOf(context, type, this) -fun KotlinTypeMarker.isSubtypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?) = +fun KotlinTypeMarker.isSubtypeOf(context: TypeCheckerProviderContext, type: KotlinTypeMarker?): Boolean = type != null && AbstractTypeChecker.isSubtypeOf(context, this, type) fun ConeKotlinType.canHaveSubtypes(session: FirSession): Boolean { @@ -380,7 +370,8 @@ private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinTy return false } -fun FirMemberDeclaration.isInlineOnly(): Boolean = isInline && (this as FirAnnotatedDeclaration).hasAnnotation(INLINE_ONLY_ANNOTATION_CLASS_ID) +fun FirMemberDeclaration.isInlineOnly(): Boolean = + isInline && (this as FirAnnotatedDeclaration).hasAnnotation(INLINE_ONLY_ANNOTATION_CLASS_ID) fun isSubtypeForTypeMismatch(context: ConeInferenceContext, subtype: ConeKotlinType, supertype: ConeKotlinType): Boolean { val subtypeFullyExpanded = subtype.fullyExpandedType(context.session) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunInterfaceDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunInterfaceDeclarationChecker.kt index a98f0e7f5c6..1097d8f5b7a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunInterfaceDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunInterfaceDeclarationChecker.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_ABSTRACT_METHOD_WITH_DEFAULT_VALUE @@ -31,6 +31,7 @@ object FirFunInterfaceDeclarationChecker : FirRegularClassChecker() { if (!declaration.isInterface || !declaration.isFun) return val scope = declaration.unsubstitutedScope(context) + val classSymbol = declaration.symbol var abstractFunction: FirSimpleFunction? = null @@ -52,7 +53,7 @@ object FirFunInterfaceDeclarationChecker : FirRegularClassChecker() { val firProperty = property.fir as? FirProperty ?: continue if (firProperty.isAbstract) { val source = - if (firProperty.getContainingClass(context) != declaration) + if (firProperty.getContainingClassSymbol(context) != classSymbol) declaration.source else firProperty.source @@ -67,7 +68,7 @@ object FirFunInterfaceDeclarationChecker : FirRegularClassChecker() { return } - val inFunInterface = abstractFunction.getContainingClass(context) === declaration + val inFunInterface = abstractFunction.getContainingClassSymbol(context) === classSymbol when { abstractFunction.typeParameters.isNotEmpty() -> diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt index 7590772b36a..3d99f48377d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData import org.jetbrains.kotlin.fir.scopes.impl.multipleDelegatesWithTheSameSignature import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.unwrapFakeOverrides import org.jetbrains.kotlin.util.ImplementationStatus @@ -166,5 +167,5 @@ object FirNotImplementedOverrideChecker : FirClassChecker() { } private fun FirCallableDeclaration.isFromInterfaceOrEnum(context: CheckerContext): Boolean = - (getContainingClass(context) as? FirRegularClass)?.let { it.isInterface || it.isEnumClass } == true + (getContainingClassSymbol(context) as? FirRegularClassSymbol)?.let { it.isInterface || it.isEnumClass } == true } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAbstractSuperCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAbstractSuperCallChecker.kt index cd98e079bcb..1cddc9e3271 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAbstractSuperCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAbstractSuperCallChecker.kt @@ -9,16 +9,17 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest -import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass -import org.jetbrains.kotlin.fir.analysis.checkers.getDeclaration import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn -import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.utils.modality +import org.jetbrains.kotlin.fir.declarations.utils.isAbstract import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.FirSuperReference +import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.utils.addToStdlib.safeAs object FirAbstractSuperCallChecker : FirQualifiedAccessExpressionChecker() { @@ -33,16 +34,11 @@ object FirAbstractSuperCallChecker : FirQualifiedAccessExpressionChecker() { if (closestClass.classKind == ClassKind.CLASS) { // handles all the FirSimpleFunction/FirProperty/etc. - val item = expression.getDeclaration() - ?: return + val declarationSymbol = expression.toResolvedCallableSymbol() ?: return - val declaration = item.getContainingClass(context).safeAs() - ?: return + val containingClassSymbol = declarationSymbol.containingClass()?.toSymbol(context.session) as? FirRegularClassSymbol ?: return - if ( - declaration.modality == Modality.ABSTRACT && - item.modality == Modality.ABSTRACT - ) { + if (containingClassSymbol.isAbstract && declarationSymbol.isAbstract) { reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuperclassNotAccessibleFromInterfaceChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuperclassNotAccessibleFromInterfaceChecker.kt index 7f3d88c0a0a..b33b6772320 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuperclassNotAccessibleFromInterfaceChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSuperclassNotAccessibleFromInterfaceChecker.kt @@ -8,14 +8,13 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest -import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression -import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -29,22 +28,12 @@ object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessExpres val closestClass = context.findClosest() ?: return if (closestClass.classKind == ClassKind.INTERFACE) { - val origin = getClassLikeDeclaration(expression, context) - ?.symbol.safeAs() - ?.fir - ?: return + val containingClassSymbol = + expression.toResolvedCallableSymbol()?.getContainingClassSymbol(context) as? FirRegularClassSymbol ?: return - if (origin.source != null && origin.classKind == ClassKind.CLASS) { + if (containingClassSymbol.classKind == ClassKind.CLASS) { reporter.reportOn(expression.explicitReceiver?.source, FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE, context) } } } - - /** - * Returns the ClassLikeDeclaration where the function has been defined - * or null if no proper declaration has been found. - */ - private fun getClassLikeDeclaration(functionCall: FirQualifiedAccessExpression, context: CheckerContext): FirClassLikeDeclaration? { - return functionCall.calleeReference.safeAs()?.resolvedSymbol?.fir?.getContainingClass(context) - } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUninitializedEnumChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUninitializedEnumChecker.kt index c2f50eea888..7d353353837 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUninitializedEnumChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUninitializedEnumChecker.kt @@ -8,8 +8,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isEnumEntryInitializer -import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass -import org.jetbrains.kotlin.fir.analysis.checkers.outerClass +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol +import org.jetbrains.kotlin.fir.analysis.checkers.outerClassSymbol import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn @@ -18,6 +18,10 @@ import org.jetbrains.kotlin.fir.declarations.utils.isCompanion import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.symbols.ensureResolved +import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { // Initialization order: member property initializers, enum entries, companion object (including members in it). @@ -68,17 +72,17 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { if (source.kind is FirFakeSourceElementKind) return val reference = expression.calleeReference as? FirResolvedNamedReference ?: return - val calleeDeclaration = reference.resolvedSymbol.fir - val calleeContainingClass = calleeDeclaration.getContainingClass(context) as? FirRegularClass ?: return + val calleeSymbol = reference.resolvedSymbol + val calleeContainingClassSymbol = calleeSymbol.getContainingClassSymbol(context) as? FirRegularClassSymbol ?: return // We're looking for members/entries/companion object in an enum class or members in companion object of an enum class. - val calleeIsInsideEnum = calleeContainingClass.isEnumClass + val calleeIsInsideEnum = calleeContainingClassSymbol.isEnumClass val calleeIsInsideEnumCompanion = - calleeContainingClass.isCompanion && (calleeContainingClass.outerClass(context) as? FirRegularClass)?.isEnumClass == true + calleeContainingClassSymbol.isCompanion && (calleeContainingClassSymbol.outerClassSymbol(context) as? FirRegularClassSymbol)?.isEnumClass == true if (!calleeIsInsideEnum && !calleeIsInsideEnumCompanion) return - val enumClass = - if (calleeIsInsideEnum) calleeContainingClass - else calleeContainingClass.outerClass(context) as? FirRegularClass ?: return + val enumClassSymbol = + if (calleeIsInsideEnum) calleeContainingClassSymbol + else calleeContainingClassSymbol.outerClassSymbol(context) as? FirRegularClassSymbol ?: return // An accessed context within the enum class of interest. We should look up until either enum members or enum entries are found, // not just last containing declaration. For example, @@ -99,11 +103,11 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { // INSTANCE(EnumCompanion2.foo()) // } // find an accessed context within the same enum class. - it.getContainingClass(context) == enumClass - } ?: return + it.getContainingClassSymbol(context) == enumClassSymbol + }?.symbol ?: return - val enumMemberProperties = enumClass.declarations.filterIsInstance() - val enumEntries = enumClass.declarations.filterIsInstance() + val enumMemberProperties = enumClassSymbol.declarationSymbols.filterIsInstance() + val enumEntries = enumClassSymbol.declarationSymbols.filterIsInstance() // When checking enum member properties, accesses to enum entries in lazy delegation is legitimate, e.g., // enum JvmTarget(...) { @@ -114,7 +118,7 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { // } // } if (accessedContext in enumMemberProperties) { - val lazyDelegation = (accessedContext as FirProperty).lazyDelegation + val lazyDelegation = (accessedContext as FirPropertySymbol).lazyDelegation if (lazyDelegation != null && lazyDelegation == context.containingDeclarations.lastOrNull()) { return } @@ -135,10 +139,10 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { } // Members inside the companion object of an enum class - if (calleeContainingClass == enumClass.companionObject) { + if (calleeContainingClassSymbol == enumClassSymbol.companionObjectSymbol) { // Uninitialized from the point of view of members or enum entries of that enum class if (accessedContext in enumMemberProperties || accessedContext in enumEntries) { - if (calleeDeclaration is FirProperty) { + if (calleeSymbol is FirProperty) { // From KT-11769 // enum class Fruit(...) { // APPLE(...); @@ -147,7 +151,7 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { // } // val score = ... common // } - reporter.reportOn(source, FirErrors.UNINITIALIZED_VARIABLE, calleeDeclaration.symbol, context) + reporter.reportOn(source, FirErrors.UNINITIALIZED_VARIABLE, calleeSymbol.symbol, context) } else { // enum class EnumCompanion2(...) { // INSTANCE(foo()) @@ -156,18 +160,18 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { // } // } // Companion.foo() v.s. foo() - if ((expression.explicitReceiver as? FirResolvedQualifier)?.symbol?.fir == enumClass.companionObject) { + if ((expression.explicitReceiver as? FirResolvedQualifier)?.symbol == enumClassSymbol.companionObjectSymbol) { reporter.reportOn( expression.explicitReceiver!!.source, FirErrors.UNINITIALIZED_ENUM_COMPANION, - enumClass.symbol, + enumClassSymbol, context ) } else { reporter.reportOn( expression.calleeReference.source, FirErrors.UNINITIALIZED_ENUM_COMPANION, - enumClass.symbol, + enumClassSymbol, context ) } @@ -176,8 +180,8 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { } // The enum entries of an enum class - if (calleeDeclaration in enumEntries) { - val calleeEnumEntry = calleeDeclaration as FirEnumEntry + if (calleeSymbol in enumEntries) { + val calleeEnumEntry = calleeSymbol as FirEnumEntrySymbol // Uninitialized from the point of view of members of that enum class if (accessedContext in enumMemberProperties) { // From KT-6054 @@ -188,7 +192,7 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { // B -> ... // } // } - reporter.reportOn(source, FirErrors.UNINITIALIZED_ENUM_ENTRY, calleeEnumEntry.symbol, context) + reporter.reportOn(source, FirErrors.UNINITIALIZED_ENUM_ENTRY, calleeEnumEntry, context) } // enum class A(...) { // A1(A2), @@ -198,7 +202,7 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { if (accessedContext in enumEntries) { // Technically, this is equal to `enumEntries.indexOf(accessedContext) <= enumEntries.indexOf(calleeDeclaration)`. // Instead of double `indexOf`, we can iterate entries just once until either one appears. - var precedingEntry: FirEnumEntry? = null + var precedingEntry: FirEnumEntrySymbol? = null enumEntries.forEach { if (precedingEntry != null) return@forEach if (it == calleeEnumEntry || it == accessedContext) { @@ -206,16 +210,17 @@ object FirUninitializedEnumChecker : FirQualifiedAccessExpressionChecker() { } } if (precedingEntry == accessedContext) { - reporter.reportOn(source, FirErrors.UNINITIALIZED_ENUM_ENTRY, calleeEnumEntry.symbol, context) + reporter.reportOn(source, FirErrors.UNINITIALIZED_ENUM_ENTRY, calleeEnumEntry, context) } } } } - private val FirProperty.lazyDelegation: FirAnonymousFunction? + private val FirPropertySymbol.lazyDelegation: FirAnonymousFunction? get() { - if (delegate == null || delegate !is FirFunctionCall) return null - val delegateCall = delegate as FirFunctionCall + ensureResolved(FirResolvePhase.BODY_RESOLVE) + if (fir.delegate == null || fir.delegate !is FirFunctionCall) return null + val delegateCall = fir.delegate as FirFunctionCall val callee = (delegateCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol?.fir as? FirSimpleFunction ?: return null if (callee.symbol.callableId.asSingleFqName().asString() != "kotlin.lazy") return null diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantVisibilityModifierSyntaxChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantVisibilityModifierSyntaxChecker.kt index ece4f7bfe8e..85d65c37820 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantVisibilityModifierSyntaxChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantVisibilityModifierSyntaxChecker.kt @@ -5,22 +5,26 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.FirFakeSourceElement import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirSourceElement -import org.jetbrains.kotlin.fir.analysis.checkers.* import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember +import org.jetbrains.kotlin.fir.analysis.checkers.findClosestClassOrObject +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol +import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirDeclarationSyntaxChecker +import org.jetbrains.kotlin.fir.analysis.checkers.toVisibilityOrNull import org.jetbrains.kotlin.fir.analysis.diagnostics.* import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass import org.jetbrains.kotlin.fir.declarations.utils.isOverride +import org.jetbrains.kotlin.fir.declarations.utils.isSealed import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.psi.KtDeclaration @@ -71,10 +75,10 @@ object RedundantVisibilityModifierSyntaxChecker : FirDeclarationSyntaxChecker { - val clazz = this.getContainingClass(context) + val classSymbol = this.getContainingClassSymbol(context) if ( - clazz is FirClass - && (clazz.classKind == ClassKind.ENUM_CLASS || clazz.modality() == Modality.SEALED) + classSymbol is FirRegularClassSymbol + && (classSymbol.isEnumClass || classSymbol.isSealed) ) { Visibilities.Private } else { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt index ff0649c330c..5f2eb479956 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt @@ -14,11 +14,12 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.cfa.* import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.isIterator import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn +import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess @@ -31,10 +32,7 @@ import org.jetbrains.kotlin.fir.types.coneType object UnusedChecker : FirControlFlowChecker() { override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext) { - if (graph.declaration?.getContainingClass(context)?.takeIf { - !it.symbol.classId.isLocal - } != null - ) return + if (graph.declaration?.getContainingClassSymbol(context)?.takeIf { !it.isLocal } != null) return val (properties, _) = LocalPropertyAndCapturedWriteCollector.collect(graph) if (properties.isEmpty()) return diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirClassLikeSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirClassLikeSymbol.kt index f94a07d90a1..69dd6728a18 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirClassLikeSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirClassLikeSymbol.kt @@ -57,6 +57,9 @@ class FirRegularClassSymbol(classId: ClassId) : FirClassSymbol( ensureResolved(FirResolvePhase.STATUS) return fir.status as FirResolvedDeclarationStatus } + + val companionObjectSymbol: FirRegularClassSymbol? + get() = fir.companionObject?.symbol } val ANONYMOUS_CLASS_ID = ClassId(FqName.ROOT, FqName.topLevel(Name.special("")), true)