FIR checker: remove inappropriate usage of FirFileChecker

This to conform with the contract expected by LL API that no file
checker should report diagnostics on its contained declarations
This commit is contained in:
Tianyu Geng
2021-12-08 12:58:40 -08:00
committed by TeamCityServer
parent 3017397960
commit d80b809a40
8 changed files with 62 additions and 67 deletions
@@ -61,6 +61,7 @@ fun main(args: Array<String>) {
val declarationPackage = "$basePackage.checkers.declaration" val declarationPackage = "$basePackage.checkers.declaration"
generateCheckersComponents(generationPath, declarationPackage, "FirDeclarationChecker") { generateCheckersComponents(generationPath, declarationPackage, "FirDeclarationChecker") {
alias<FirDeclaration>("BasicDeclarationChecker") alias<FirDeclaration>("BasicDeclarationChecker")
alias<FirCallableDeclaration>("CallableDeclarationChecker")
alias<FirFunction>("FunctionChecker") alias<FirFunction>("FunctionChecker")
alias<FirSimpleFunction>("SimpleFunctionChecker") alias<FirSimpleFunction>("SimpleFunctionChecker")
alias<FirProperty>("PropertyChecker") alias<FirProperty>("PropertyChecker")
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
class ComposedDeclarationCheckers : DeclarationCheckers() { class ComposedDeclarationCheckers : DeclarationCheckers() {
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
get() = _basicDeclarationCheckers get() = _basicDeclarationCheckers
override val callableDeclarationCheckers: Set<FirCallableDeclarationChecker>
get() = _callableDeclarationCheckers
override val functionCheckers: Set<FirFunctionChecker> override val functionCheckers: Set<FirFunctionChecker>
get() = _functionCheckers get() = _functionCheckers
override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker> override val simpleFunctionCheckers: Set<FirSimpleFunctionChecker>
@@ -57,6 +59,7 @@ class ComposedDeclarationCheckers : DeclarationCheckers() {
get() = _variableAssignmentCfaBasedCheckers get() = _variableAssignmentCfaBasedCheckers
private val _basicDeclarationCheckers: MutableSet<FirBasicDeclarationChecker> = mutableSetOf() private val _basicDeclarationCheckers: MutableSet<FirBasicDeclarationChecker> = mutableSetOf()
private val _callableDeclarationCheckers: MutableSet<FirCallableDeclarationChecker> = mutableSetOf()
private val _functionCheckers: MutableSet<FirFunctionChecker> = mutableSetOf() private val _functionCheckers: MutableSet<FirFunctionChecker> = mutableSetOf()
private val _simpleFunctionCheckers: MutableSet<FirSimpleFunctionChecker> = mutableSetOf() private val _simpleFunctionCheckers: MutableSet<FirSimpleFunctionChecker> = mutableSetOf()
private val _propertyCheckers: MutableSet<FirPropertyChecker> = mutableSetOf() private val _propertyCheckers: MutableSet<FirPropertyChecker> = mutableSetOf()
@@ -80,6 +83,7 @@ class ComposedDeclarationCheckers : DeclarationCheckers() {
@CheckersComponentInternal @CheckersComponentInternal
fun register(checkers: DeclarationCheckers) { fun register(checkers: DeclarationCheckers) {
_basicDeclarationCheckers += checkers.basicDeclarationCheckers _basicDeclarationCheckers += checkers.basicDeclarationCheckers
_callableDeclarationCheckers += checkers.callableDeclarationCheckers
_functionCheckers += checkers.functionCheckers _functionCheckers += checkers.functionCheckers
_simpleFunctionCheckers += checkers.simpleFunctionCheckers _simpleFunctionCheckers += checkers.simpleFunctionCheckers
_propertyCheckers += checkers.propertyCheckers _propertyCheckers += checkers.propertyCheckers
@@ -20,6 +20,7 @@ abstract class DeclarationCheckers {
} }
open val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = emptySet() open val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = emptySet()
open val callableDeclarationCheckers: Set<FirCallableDeclarationChecker> = emptySet()
open val functionCheckers: Set<FirFunctionChecker> = emptySet() open val functionCheckers: Set<FirFunctionChecker> = emptySet()
open val simpleFunctionCheckers: Set<FirSimpleFunctionChecker> = emptySet() open val simpleFunctionCheckers: Set<FirSimpleFunctionChecker> = emptySet()
open val propertyCheckers: Set<FirPropertyChecker> = emptySet() open val propertyCheckers: Set<FirPropertyChecker> = emptySet()
@@ -42,21 +43,22 @@ abstract class DeclarationCheckers {
open val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker> = emptySet() open val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker> = emptySet()
@CheckersComponentInternal internal val allBasicDeclarationCheckers: Set<FirBasicDeclarationChecker> by lazy { basicDeclarationCheckers } @CheckersComponentInternal internal val allBasicDeclarationCheckers: Set<FirBasicDeclarationChecker> by lazy { basicDeclarationCheckers }
@CheckersComponentInternal internal val allFunctionCheckers: Set<FirFunctionChecker> by lazy { functionCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allCallableDeclarationCheckers: Set<FirCallableDeclarationChecker> by lazy { callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allSimpleFunctionCheckers: Set<FirSimpleFunctionChecker> by lazy { simpleFunctionCheckers + functionCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allFunctionCheckers: Set<FirFunctionChecker> by lazy { functionCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allPropertyCheckers: Set<FirPropertyChecker> by lazy { propertyCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allSimpleFunctionCheckers: Set<FirSimpleFunctionChecker> by lazy { simpleFunctionCheckers + functionCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allPropertyCheckers: Set<FirPropertyChecker> by lazy { propertyCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allClassLikeCheckers: Set<FirClassLikeChecker> by lazy { classLikeCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allClassLikeCheckers: Set<FirClassLikeChecker> by lazy { classLikeCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allClassCheckers: Set<FirClassChecker> by lazy { classCheckers + classLikeCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allClassCheckers: Set<FirClassChecker> by lazy { classCheckers + classLikeCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> by lazy { regularClassCheckers + classCheckers + classLikeCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> by lazy { regularClassCheckers + classCheckers + classLikeCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> by lazy { constructorCheckers + functionCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> by lazy { constructorCheckers + functionCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> by lazy { fileCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> by lazy { fileCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allTypeParameterCheckers: Set<FirTypeParameterChecker> by lazy { typeParameterCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allTypeParameterCheckers: Set<FirTypeParameterChecker> by lazy { typeParameterCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allTypeAliasCheckers: Set<FirTypeAliasChecker> by lazy { typeAliasCheckers + classLikeCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allTypeAliasCheckers: Set<FirTypeAliasChecker> by lazy { typeAliasCheckers + classLikeCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allAnonymousFunctionCheckers: Set<FirAnonymousFunctionChecker> by lazy { anonymousFunctionCheckers + functionCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allAnonymousFunctionCheckers: Set<FirAnonymousFunctionChecker> by lazy { anonymousFunctionCheckers + functionCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allPropertyAccessorCheckers: Set<FirPropertyAccessorChecker> by lazy { propertyAccessorCheckers + functionCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allPropertyAccessorCheckers: Set<FirPropertyAccessorChecker> by lazy { propertyAccessorCheckers + functionCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allBackingFieldCheckers: Set<FirBackingFieldChecker> by lazy { backingFieldCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allBackingFieldCheckers: Set<FirBackingFieldChecker> by lazy { backingFieldCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allValueParameterCheckers: Set<FirValueParameterChecker> by lazy { valueParameterCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allValueParameterCheckers: Set<FirValueParameterChecker> by lazy { valueParameterCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allEnumEntryCheckers: Set<FirEnumEntryChecker> by lazy { enumEntryCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allEnumEntryCheckers: Set<FirEnumEntryChecker> by lazy { enumEntryCheckers + callableDeclarationCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allAnonymousObjectCheckers: Set<FirAnonymousObjectChecker> by lazy { anonymousObjectCheckers + classCheckers + classLikeCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allAnonymousObjectCheckers: Set<FirAnonymousObjectChecker> by lazy { anonymousObjectCheckers + classCheckers + classLikeCheckers + basicDeclarationCheckers }
@CheckersComponentInternal internal val allAnonymousInitializerCheckers: Set<FirAnonymousInitializerChecker> by lazy { anonymousInitializerCheckers + basicDeclarationCheckers } @CheckersComponentInternal internal val allAnonymousInitializerCheckers: Set<FirAnonymousInitializerChecker> by lazy { anonymousInitializerCheckers + basicDeclarationCheckers }
} }
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirAnonymousInitializer import org.jetbrains.kotlin.fir.declarations.FirAnonymousInitializer
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
import org.jetbrains.kotlin.fir.declarations.FirBackingField import org.jetbrains.kotlin.fir.declarations.FirBackingField
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirConstructor
@@ -30,6 +31,7 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter
typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration> typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration>
typealias FirCallableDeclarationChecker = FirDeclarationChecker<FirCallableDeclaration>
typealias FirFunctionChecker = FirDeclarationChecker<FirFunction> typealias FirFunctionChecker = FirDeclarationChecker<FirFunction>
typealias FirSimpleFunctionChecker = FirDeclarationChecker<FirSimpleFunction> typealias FirSimpleFunctionChecker = FirDeclarationChecker<FirSimpleFunction>
typealias FirPropertyChecker = FirDeclarationChecker<FirProperty> typealias FirPropertyChecker = FirDeclarationChecker<FirProperty>
@@ -35,6 +35,11 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirOptInMarkedDeclarationChecker, FirOptInMarkedDeclarationChecker,
) )
override val callableDeclarationCheckers: Set<FirCallableDeclarationChecker>
get() = setOf(
FirKClassWithIncorrectTypeArgumentChecker,
)
override val functionCheckers: Set<FirFunctionChecker> override val functionCheckers: Set<FirFunctionChecker>
get() = setOf( get() = setOf(
FirContractChecker, FirContractChecker,
@@ -49,6 +54,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirFunctionTypeParametersSyntaxChecker, FirFunctionTypeParametersSyntaxChecker,
FirOperatorModifierChecker, FirOperatorModifierChecker,
FirTailrecFunctionChecker, FirTailrecFunctionChecker,
FirTopLevelFunctionsChecker,
) )
override val propertyCheckers: Set<FirPropertyChecker> override val propertyCheckers: Set<FirPropertyChecker>
@@ -65,6 +71,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirPropertyFromParameterChecker, FirPropertyFromParameterChecker,
FirLocalVariableTypeParametersSyntaxChecker, FirLocalVariableTypeParametersSyntaxChecker,
FirDelegateUsesExtensionPropertyTypeParameterChecker, FirDelegateUsesExtensionPropertyTypeParameterChecker,
FirTopLevelPropertiesChecker,
) )
override val backingFieldCheckers: Set<FirBackingFieldChecker> override val backingFieldCheckers: Set<FirBackingFieldChecker>
@@ -116,9 +123,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
override val fileCheckers: Set<FirFileChecker> override val fileCheckers: Set<FirFileChecker>
get() = setOf( get() = setOf(
FirKClassWithIncorrectTypeArgumentChecker,
FirTopLevelFunctionsChecker,
FirTopLevelPropertiesChecker,
FirImportsChecker, FirImportsChecker,
FirUnresolvedInMiddleOfImportChecker, FirUnresolvedInMiddleOfImportChecker,
) )
@@ -6,36 +6,26 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeTypeParameterInQualifiedAccess import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeTypeParameterInQualifiedAccess
import org.jetbrains.kotlin.fir.types.isKClassType
import org.jetbrains.kotlin.fir.scopes.impl.toConeType import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
// See FE1.0 [KClassWithIncorrectTypeArgumentChecker] // See FE1.0 [KClassWithIncorrectTypeArgumentChecker]
object FirKClassWithIncorrectTypeArgumentChecker : FirFileChecker() { object FirKClassWithIncorrectTypeArgumentChecker : FirCallableDeclarationChecker() {
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
for (topLevelDeclaration in declaration.declarations) {
if (topLevelDeclaration is FirCallableDeclaration) {
checkTopLevelDeclaration(topLevelDeclaration, context, reporter)
}
}
}
// When a type parameter is used as a type argument for KClass, it shouldn't be nullable. override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
// bad: fun <T> test1() = T::class // Only report on top level callable declarations
// okay: fun <T: Any> test2() = T::class if (context.containingDeclarations.size > 1) return
private fun checkTopLevelDeclaration(
declaration: FirCallableDeclaration, // When a type parameter is used as a type argument for KClass, it shouldn't be nullable.
context: CheckerContext, // bad: fun <T> test1() = T::class
reporter: DiagnosticReporter // okay: fun <T: Any> test2() = T::class
) {
val source = declaration.source ?: return val source = declaration.source ?: return
if (source.kind is KtFakeSourceElementKind) return if (source.kind is KtFakeSourceElementKind) return
@@ -6,12 +6,11 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.hasBody import org.jetbrains.kotlin.fir.declarations.utils.hasBody
import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.isExpect
@@ -19,26 +18,21 @@ import org.jetbrains.kotlin.fir.declarations.utils.isExternal
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
// See old FE's [DeclarationsChecker] // See old FE's [DeclarationsChecker]
object FirTopLevelFunctionsChecker : FirFileChecker() { object FirTopLevelFunctionsChecker : FirSimpleFunctionChecker() {
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) {
for (topLevelDeclaration in declaration.declarations) { // Only report on top level callable declarations
if (topLevelDeclaration is FirSimpleFunction) { if (context.containingDeclarations.size > 1) return
checkFunction(topLevelDeclaration, reporter, context)
}
}
}
private fun checkFunction(function: FirSimpleFunction, reporter: DiagnosticReporter, context: CheckerContext) { val source = declaration.source ?: return
val source = function.source ?: return
if (source.kind is KtFakeSourceElementKind) return if (source.kind is KtFakeSourceElementKind) return
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`. // If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
// So, our source of truth should be the full modifier list retrieved from the source. // So, our source of truth should be the full modifier list retrieved from the source.
if (function.hasModifier(KtTokens.ABSTRACT_KEYWORD)) return if (declaration.hasModifier(KtTokens.ABSTRACT_KEYWORD)) return
if (function.isExternal) return if (declaration.isExternal) return
if (!function.hasBody && !function.isExpect) { if (!declaration.hasBody && !declaration.isExpect) {
reporter.reportOn(source, FirErrors.NON_MEMBER_FUNCTION_NO_BODY, function.symbol, context) reporter.reportOn(source, FirErrors.NON_MEMBER_FUNCTION_NO_BODY, declaration.symbol, context)
} }
checkExpectDeclarationVisibilityAndBody(function, source, reporter, context) checkExpectDeclarationVisibilityAndBody(declaration, source, reporter, context)
} }
} }
@@ -8,15 +8,18 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.FirModifierList import org.jetbrains.kotlin.fir.analysis.checkers.FirModifierList
import org.jetbrains.kotlin.fir.analysis.checkers.contains import org.jetbrains.kotlin.fir.analysis.checkers.contains
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeLocalVariableNoTypeOrInitializer import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeLocalVariableNoTypeOrInitializer
@@ -24,32 +27,27 @@ import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
// See old FE's [DeclarationsChecker] // See old FE's [DeclarationsChecker]
object FirTopLevelPropertiesChecker : FirFileChecker() { object FirTopLevelPropertiesChecker : FirPropertyChecker() {
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
for (topLevelDeclaration in declaration.declarations) { // Only report on top level callable declarations
if (topLevelDeclaration is FirProperty) { if (context.containingDeclarations.size > 1) return
checkProperty(topLevelDeclaration, reporter, context)
}
}
}
private fun checkProperty(property: FirProperty, reporter: DiagnosticReporter, context: CheckerContext) { val source = declaration.source ?: return
val source = property.source ?: return
if (source.kind is KtFakeSourceElementKind) return if (source.kind is KtFakeSourceElementKind) return
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`. // If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
// So, our source of truth should be the full modifier list retrieved from the source. // So, our source of truth should be the full modifier list retrieved from the source.
val modifierList = source.getModifierList() val modifierList = source.getModifierList()
withSuppressedDiagnostics(property, context) { withSuppressedDiagnostics(declaration, context) {
checkPropertyInitializer( checkPropertyInitializer(
containingClass = null, containingClass = null,
property, declaration,
modifierList, modifierList,
isInitialized = property.initializer != null, isInitialized = declaration.initializer != null,
reporter, reporter,
context context
) )
checkExpectDeclarationVisibilityAndBody(property, source, reporter, context) checkExpectDeclarationVisibilityAndBody(declaration, source, reporter, context)
} }
} }
} }