[FIR] Replace getContainingClass usages with getContainingClassSymbol
This commit is contained in:
committed by
teamcityserver
parent
48a25e2fe6
commit
c99a02796f
+1
-1
@@ -242,7 +242,7 @@ internal object ConeTypeCompatibilityChecker {
|
||||
|
||||
private fun FirTypeParameterSymbol?.collectUpperBounds(): Set<ConeClassLikeType> {
|
||||
if (this == null) return emptySet()
|
||||
return fir.bounds.flatMap { it.coneTypeSafe<ConeKotlinType>().collectUpperBounds() }.toSet()
|
||||
return resolvedBounds.flatMap { it.coneTypeSafe<ConeKotlinType>().collectUpperBounds() }.toSet()
|
||||
}
|
||||
|
||||
private fun ConeKotlinType?.collectLowerBounds(): Set<ConeClassLikeType> {
|
||||
|
||||
+15
-24
@@ -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 <reified T : Any> FirQualifiedAccessExpression.getDeclaration(): T? {
|
||||
return this.calleeReference.safeAs<FirResolvedNamedReference>()
|
||||
?.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<FirCallableDeclaration>()?.containingClass()?.toSymbol(context.session)?.fir
|
||||
fun FirDeclaration.getContainingClassSymbol(context: CheckerContext): FirClassLikeSymbol<*>? =
|
||||
this.safeAs<FirCallableDeclaration>()?.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() == "<iterator>"
|
||||
|
||||
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)
|
||||
|
||||
+4
-3
@@ -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() ->
|
||||
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
|
||||
+8
-12
@@ -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<FirCallableDeclaration>()
|
||||
?: return
|
||||
val declarationSymbol = expression.toResolvedCallableSymbol() ?: return
|
||||
|
||||
val declaration = item.getContainingClass(context).safeAs<FirRegularClass>()
|
||||
?: 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)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-16
@@ -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<FirRegularClass>() ?: return
|
||||
|
||||
if (closestClass.classKind == ClassKind.INTERFACE) {
|
||||
val origin = getClassLikeDeclaration(expression, context)
|
||||
?.symbol.safeAs<FirRegularClassSymbol>()
|
||||
?.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<FirResolvedNamedReference>()?.resolvedSymbol?.fir?.getContainingClass(context)
|
||||
}
|
||||
}
|
||||
|
||||
+33
-28
@@ -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<FirProperty>()
|
||||
val enumEntries = enumClass.declarations.filterIsInstance<FirEnumEntry>()
|
||||
val enumMemberProperties = enumClassSymbol.declarationSymbols.filterIsInstance<FirPropertySymbol>()
|
||||
val enumEntries = enumClassSymbol.declarationSymbols.filterIsInstance<FirEnumEntrySymbol>()
|
||||
|
||||
// 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
|
||||
|
||||
+10
-6
@@ -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<Fi
|
||||
}
|
||||
|
||||
this is FirConstructor -> {
|
||||
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 {
|
||||
|
||||
+3
-5
@@ -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
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@ class FirRegularClassSymbol(classId: ClassId) : FirClassSymbol<FirRegularClass>(
|
||||
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("<anonymous>")), true)
|
||||
|
||||
Reference in New Issue
Block a user