FIR checker: Create a new kind of checker FirTypeChecker and add
FirSuspendModifierChecker to report WRONG_MODIFIER_TARGET for `suspend` on non-functional types.
This commit is contained in:
committed by
TeamCityServer
parent
4282d17467
commit
e69b729e21
+6
@@ -9,11 +9,17 @@ import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DIAGNOSTICS_LIST
|
|||||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.generateDiagnostics
|
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.generateDiagnostics
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val generationPath = args.firstOrNull()?.let { File(it) } ?: File("compiler/fir/checkers/gen").absoluteFile
|
val generationPath = args.firstOrNull()?.let { File(it) } ?: File("compiler/fir/checkers/gen").absoluteFile
|
||||||
|
|
||||||
|
val typePackage = "org.jetbrains.kotlin.fir.analysis.checkers.type"
|
||||||
|
generateCheckersComponents(generationPath, typePackage, "FirTypeChecker") {
|
||||||
|
alias<FirTypeRef>("TypeRefChecker")
|
||||||
|
}
|
||||||
|
|
||||||
val expressionPackage = "org.jetbrains.kotlin.fir.analysis.checkers.expression"
|
val expressionPackage = "org.jetbrains.kotlin.fir.analysis.checkers.expression"
|
||||||
generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") {
|
generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") {
|
||||||
alias<FirStatement>("BasicExpressionChecker")
|
alias<FirStatement>("BasicExpressionChecker")
|
||||||
|
|||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was generated automatically
|
||||||
|
* DO NOT MODIFY IT MANUALLY
|
||||||
|
*/
|
||||||
|
|
||||||
|
internal class ComposedTypeCheckers : TypeCheckers() {
|
||||||
|
override val typeRefCheckers: Set<FirTypeRefChecker>
|
||||||
|
get() = _typeRefCheckers
|
||||||
|
|
||||||
|
private val _typeRefCheckers: MutableSet<FirTypeRefChecker> = mutableSetOf()
|
||||||
|
|
||||||
|
@CheckersComponentInternal
|
||||||
|
internal fun register(checkers: TypeCheckers) {
|
||||||
|
_typeRefCheckers += checkers.typeRefCheckers
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was generated automatically
|
||||||
|
* DO NOT MODIFY IT MANUALLY
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
|
|
||||||
|
typealias FirTypeRefChecker = FirTypeChecker<FirTypeRef>
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was generated automatically
|
||||||
|
* DO NOT MODIFY IT MANUALLY
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class TypeCheckers {
|
||||||
|
companion object {
|
||||||
|
val EMPTY: TypeCheckers = object : TypeCheckers() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
open val typeRefCheckers: Set<FirTypeRefChecker> = emptySet()
|
||||||
|
|
||||||
|
@CheckersComponentInternal internal val allTypeRefCheckers: Set<FirTypeRefChecker> get() = typeRefCheckers
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.ComposedDeclaratio
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ComposedExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ComposedExpressionCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.ComposedTypeCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
|
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
|
||||||
|
|
||||||
@RequiresOptIn
|
@RequiresOptIn
|
||||||
@@ -26,6 +28,9 @@ class CheckersComponent : FirSessionComponent {
|
|||||||
val expressionCheckers: ExpressionCheckers get() = _expressionCheckers
|
val expressionCheckers: ExpressionCheckers get() = _expressionCheckers
|
||||||
private val _expressionCheckers = ComposedExpressionCheckers()
|
private val _expressionCheckers = ComposedExpressionCheckers()
|
||||||
|
|
||||||
|
val typeCheckers: TypeCheckers get() = _typeCheckers
|
||||||
|
private val _typeCheckers = ComposedTypeCheckers()
|
||||||
|
|
||||||
@SessionConfiguration
|
@SessionConfiguration
|
||||||
@OptIn(CheckersComponentInternal::class)
|
@OptIn(CheckersComponentInternal::class)
|
||||||
fun register(checkers: DeclarationCheckers) {
|
fun register(checkers: DeclarationCheckers) {
|
||||||
@@ -38,10 +43,17 @@ class CheckersComponent : FirSessionComponent {
|
|||||||
_expressionCheckers.register(checkers)
|
_expressionCheckers.register(checkers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SessionConfiguration
|
||||||
|
@OptIn(CheckersComponentInternal::class)
|
||||||
|
fun register(checkers: TypeCheckers) {
|
||||||
|
_typeCheckers.register(checkers)
|
||||||
|
}
|
||||||
|
|
||||||
@SessionConfiguration
|
@SessionConfiguration
|
||||||
fun register(checkers: FirAdditionalCheckersExtension) {
|
fun register(checkers: FirAdditionalCheckersExtension) {
|
||||||
register(checkers.declarationCheckers)
|
register(checkers.declarationCheckers)
|
||||||
register(checkers.expressionCheckers)
|
register(checkers.expressionCheckers)
|
||||||
|
register(checkers.typeCheckers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-59
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|
||||||
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.FirFile
|
|
||||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRefWithNullability
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
|
||||||
|
|
||||||
object FirSuspendOnInvalidTypeChecker : FirFileChecker() {
|
|
||||||
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
|
||||||
// Traverse the entire file to look for source type refs (i.e., Fir(Dynamic|User|Function)TypeRef).
|
|
||||||
declaration.accept(object : FirDefaultVisitorVoid() {
|
|
||||||
override fun visitElement(element: FirElement) {
|
|
||||||
if (element.source?.kind is FirFakeSourceElementKind) return
|
|
||||||
element.acceptChildren(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef) {
|
|
||||||
// We will only get to the source type refs by visiting delegatedTypeRef.
|
|
||||||
super.visitResolvedTypeRef(resolvedTypeRef)
|
|
||||||
resolvedTypeRef.delegatedTypeRef?.accept(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitTypeRefWithNullability(typeRefWithNullability: FirTypeRefWithNullability) {
|
|
||||||
// `suspend` is invalid for non-function types (i.e., FirDynamicTypeRef or FirUserTypeRef).
|
|
||||||
//
|
|
||||||
// It is also invalid for nullable function types, e.g., `suspend (() -> Int)?`.
|
|
||||||
// The correct way to denote a nullable suspend function type is `(suspend () -> Int)?`.
|
|
||||||
// In both cases, the source for the FirFunctionTypeRef is the TYPE_REFERENCE element.
|
|
||||||
// In the invalid case, the modifier list is in the source TYPE_REFERENCE element.
|
|
||||||
// But in the correct case, the modifier list is in the child NULLABLE_TYPE element.
|
|
||||||
// Therefore, if the FirFunctionTypeRef is marked nullable, it is invalid to HAVE the `suspend` modifier
|
|
||||||
// on the source element, even though it seems counter-intuitive.
|
|
||||||
val suspendModifier = typeRefWithNullability.getModifier(KtTokens.SUSPEND_KEYWORD) ?: return
|
|
||||||
if (typeRefWithNullability !is FirFunctionTypeRef || typeRefWithNullability.isMarkedNullable) {
|
|
||||||
reporter.reportOn(
|
|
||||||
suspendModifier.source,
|
|
||||||
FirErrors.WRONG_MODIFIER_TARGET,
|
|
||||||
suspendModifier.token,
|
|
||||||
"non-functional type",
|
|
||||||
context
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.getModifier
|
||||||
|
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.types.FirFunctionTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRefWithNullability
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
|
object FirSuspendModifierChecker : FirTypeRefChecker() {
|
||||||
|
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
// We are only interested in source type refs (i.e., Fir(Dynamic|User|Function)TypeRef).
|
||||||
|
if (typeRef !is FirTypeRefWithNullability) return
|
||||||
|
|
||||||
|
val suspendModifier = typeRef.getModifier(KtTokens.SUSPEND_KEYWORD) ?: return
|
||||||
|
|
||||||
|
// `suspend` is invalid for non-function types (i.e., FirDynamicTypeRef or FirUserTypeRef).
|
||||||
|
//
|
||||||
|
// It is also invalid for nullable function types, e.g., `suspend (() -> Int)?`.
|
||||||
|
// The correct way to denote a nullable suspend function type is `(suspend () -> Int)?`.
|
||||||
|
// (To clarify: You can "mark nullable" a suspend function type, but you cannot "mark suspend" a nullable function type.)
|
||||||
|
//
|
||||||
|
// In both invalid and correct cases, the source for the FirFunctionTypeRef is the TYPE_REFERENCE element.
|
||||||
|
// In the invalid case, the `suspend` modifier is in the source TYPE_REFERENCE element.
|
||||||
|
// But in the correct case, the `suspend` modifier is in the child NULLABLE_TYPE element, i.e., the source TYPE_REFERENCE element
|
||||||
|
// will not have the `suspend` modifier.
|
||||||
|
//
|
||||||
|
// In both cases, the FirFunctionTypeRef is marked nullable. But it is invalid to have the `suspend` modifier on the source element.
|
||||||
|
if (typeRef !is FirFunctionTypeRef || typeRef.isMarkedNullable) {
|
||||||
|
reporter.reportOn(
|
||||||
|
suspendModifier.source,
|
||||||
|
FirErrors.WRONG_MODIFIER_TARGET,
|
||||||
|
suspendModifier.token,
|
||||||
|
"non-functional type",
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
|
|
||||||
|
abstract class FirTypeChecker<in T : FirTypeRef> {
|
||||||
|
/**
|
||||||
|
* [FirTypeChecker] should only be used when the check can be performed independent of the context of the type refs. That is,
|
||||||
|
* you should NOT be examining containing declarations, qualified accesses, etc. when writing a FirTypeChecker.
|
||||||
|
*
|
||||||
|
* If the check is dependent on context, or if it is specific to type refs in a certain kind of declaration or expression,
|
||||||
|
* please write a [org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker] or
|
||||||
|
* [org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker] instead.
|
||||||
|
*/
|
||||||
|
abstract fun check(typeRef: T, context: CheckerContext, reporter: DiagnosticReporter)
|
||||||
|
}
|
||||||
+1
@@ -72,6 +72,7 @@ fun AbstractDiagnosticCollector.registerAllComponents() {
|
|||||||
initializeComponents(
|
initializeComponents(
|
||||||
DeclarationCheckersDiagnosticComponent(this),
|
DeclarationCheckersDiagnosticComponent(this),
|
||||||
ExpressionCheckersDiagnosticComponent(this),
|
ExpressionCheckersDiagnosticComponent(this),
|
||||||
|
TypeCheckersDiagnosticComponent(this),
|
||||||
ErrorNodeDiagnosticCollectorComponent(this),
|
ErrorNodeDiagnosticCollectorComponent(this),
|
||||||
ControlFlowAnalysisDiagnosticComponent(this),
|
ControlFlowAnalysisDiagnosticComponent(this),
|
||||||
)
|
)
|
||||||
|
|||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
|
||||||
|
@OptIn(CheckersComponentInternal::class)
|
||||||
|
class TypeCheckersDiagnosticComponent(
|
||||||
|
collector: AbstractDiagnosticCollector,
|
||||||
|
private val checkers: TypeCheckers = collector.session.checkersComponent.typeCheckers,
|
||||||
|
) : AbstractDiagnosticCollectorComponent(collector) {
|
||||||
|
|
||||||
|
override fun visitDynamicTypeRef(dynamicTypeRef: FirDynamicTypeRef, data: CheckerContext) {
|
||||||
|
checkers.allTypeRefCheckers.check(dynamicTypeRef, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunctionTypeRef(functionTypeRef: FirFunctionTypeRef, data: CheckerContext) {
|
||||||
|
checkers.allTypeRefCheckers.check(functionTypeRef, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitUserTypeRef(userTypeRef: FirUserTypeRef, data: CheckerContext) {
|
||||||
|
checkers.allTypeRefCheckers.check(userTypeRef, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: CheckerContext) {
|
||||||
|
checkers.allTypeRefCheckers.check(resolvedTypeRef, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) {
|
||||||
|
checkers.allTypeRefCheckers.check(errorTypeRef, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeRefWithNullability(typeRefWithNullability: FirTypeRefWithNullability, data: CheckerContext) {
|
||||||
|
checkers.allTypeRefCheckers.check(typeRefWithNullability, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: CheckerContext) {
|
||||||
|
checkers.allTypeRefCheckers.check(implicitTypeRef, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeRef(typeRef: FirTypeRef, data: CheckerContext) {
|
||||||
|
checkers.allTypeRefCheckers.check(typeRef, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : FirTypeRef> Collection<FirTypeChecker<T>>.check(
|
||||||
|
typeRef: T,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
|
for (checker in this) {
|
||||||
|
checker.check(typeRef, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.extensions
|
|||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||||
import org.jetbrains.kotlin.fir.extensions.AbstractFirAdditionalCheckersExtension
|
import org.jetbrains.kotlin.fir.extensions.AbstractFirAdditionalCheckersExtension
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionPointName
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionPointName
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionService
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionService
|
||||||
@@ -19,6 +20,7 @@ abstract class FirAdditionalCheckersExtension(session: FirSession) : AbstractFir
|
|||||||
|
|
||||||
open val declarationCheckers: DeclarationCheckers = DeclarationCheckers.EMPTY
|
open val declarationCheckers: DeclarationCheckers = DeclarationCheckers.EMPTY
|
||||||
open val expressionCheckers: ExpressionCheckers = ExpressionCheckers.EMPTY
|
open val expressionCheckers: ExpressionCheckers = ExpressionCheckers.EMPTY
|
||||||
|
open val typeCheckers: TypeCheckers = TypeCheckers.EMPTY
|
||||||
|
|
||||||
final override val name: FirExtensionPointName
|
final override val name: FirExtensionPointName
|
||||||
get() = NAME
|
get() = NAME
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.session.FirSessionFactory
|
|||||||
fun FirSessionFactory.FirSessionConfigurator.registerCommonCheckers() {
|
fun FirSessionFactory.FirSessionConfigurator.registerCommonCheckers() {
|
||||||
useCheckers(CommonDeclarationCheckers)
|
useCheckers(CommonDeclarationCheckers)
|
||||||
useCheckers(CommonExpressionCheckers)
|
useCheckers(CommonExpressionCheckers)
|
||||||
|
useCheckers(CommonTypeCheckers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FirSessionFactory.FirSessionConfigurator.registerExtendedCommonCheckers() {
|
fun FirSessionFactory.FirSessionConfigurator.registerExtendedCommonCheckers() {
|
||||||
|
|||||||
-1
@@ -95,7 +95,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirKClassWithIncorrectTypeArgumentChecker,
|
FirKClassWithIncorrectTypeArgumentChecker,
|
||||||
FirTopLevelFunctionsChecker,
|
FirTopLevelFunctionsChecker,
|
||||||
FirTopLevelPropertiesChecker,
|
FirTopLevelPropertiesChecker,
|
||||||
FirSuspendOnInvalidTypeChecker,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
|
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.FirCallsEffectAnalyzer
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.FirPropertyInitializationAnalyzer
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirSuspendModifierChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeRefChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||||
|
|
||||||
|
object CommonTypeCheckers : TypeCheckers() {
|
||||||
|
override val typeRefCheckers: Set<FirTypeRefChecker> = setOf(
|
||||||
|
FirSuspendModifierChecker
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
|||||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
||||||
import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers
|
import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers
|
||||||
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
|
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
|
||||||
@@ -53,6 +54,10 @@ object FirSessionFactory {
|
|||||||
session.checkersComponent.register(checkers)
|
session.checkersComponent.register(checkers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun useCheckers(checkers: TypeCheckers) {
|
||||||
|
session.checkersComponent.register(checkers)
|
||||||
|
}
|
||||||
|
|
||||||
@SessionConfiguration
|
@SessionConfiguration
|
||||||
fun configure() {
|
fun configure() {
|
||||||
session.extensionService.registerExtensions(registeredExtensions.reduce(BunchOfRegisteredExtensions::plus))
|
session.extensionService.registerExtensions(registeredExtensions.reduce(BunchOfRegisteredExtensions::plus))
|
||||||
|
|||||||
+2
-1
@@ -22,7 +22,8 @@ typealias Test15 = (@A() suspend () -> Unit)?
|
|||||||
typealias Test16 = (@A suspend () -> Unit)?
|
typealias Test16 = (@A suspend () -> Unit)?
|
||||||
typealias Test17 = @A suspend RS.() -> Unit
|
typealias Test17 = @A suspend RS.() -> Unit
|
||||||
typealias Test18 = (suspend () -> Unit)?
|
typealias Test18 = (suspend () -> Unit)?
|
||||||
typealias Test19 = (@A({ val x: <!WRONG_MODIFIER_TARGET!>suspend<!> String? = null; "" }()) suspend () -> Unit)?
|
typealias Test19 = (@A({ val x: <!WRONG_MODIFIER_TARGET, WRONG_MODIFIER_TARGET!>suspend<!> String? = null; "" }()) suspend () -> Unit)?
|
||||||
|
typealias Test20 = (@A("".let { val x: <!WRONG_MODIFIER_TARGET, WRONG_MODIFIER_TARGET!>suspend<!> String? = null; it }) suspend () -> Unit)?
|
||||||
|
|
||||||
interface Supertype1 : suspend () -> Unit {
|
interface Supertype1 : suspend () -> Unit {
|
||||||
|
|
||||||
|
|||||||
+1
@@ -23,6 +23,7 @@ typealias Test16 = (@A suspend () -> Unit)?
|
|||||||
typealias Test17 = @A suspend RS.() -> Unit
|
typealias Test17 = @A suspend RS.() -> Unit
|
||||||
typealias Test18 = (suspend () -> Unit)?
|
typealias Test18 = (suspend () -> Unit)?
|
||||||
typealias Test19 = (@A(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>{ val x: <!WRONG_MODIFIER_TARGET, WRONG_MODIFIER_TARGET!>suspend<!> String? = null; "" }()<!>) suspend () -> Unit)?
|
typealias Test19 = (@A(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>{ val x: <!WRONG_MODIFIER_TARGET, WRONG_MODIFIER_TARGET!>suspend<!> String? = null; "" }()<!>) suspend () -> Unit)?
|
||||||
|
typealias Test20 = (@A(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>"".let { val x: <!WRONG_MODIFIER_TARGET, WRONG_MODIFIER_TARGET!>suspend<!> String? = null; it }<!>) suspend () -> Unit)?
|
||||||
|
|
||||||
interface Supertype1 : <!SUPERTYPE_IS_SUSPEND_FUNCTION_TYPE!>suspend () -> Unit<!> {
|
interface Supertype1 : <!SUPERTYPE_IS_SUSPEND_FUNCTION_TYPE!>suspend () -> Unit<!> {
|
||||||
|
|
||||||
|
|||||||
+1
@@ -47,6 +47,7 @@ public typealias Test17 = (@A suspend RS.() -> kotlin.Unit)
|
|||||||
public typealias Test18 = (suspend () -> kotlin.Unit)?
|
public typealias Test18 = (suspend () -> kotlin.Unit)?
|
||||||
public typealias Test19 = (@A suspend () -> kotlin.Unit)?
|
public typealias Test19 = (@A suspend () -> kotlin.Unit)?
|
||||||
public typealias Test2 = suspend kotlin.Int.() -> kotlin.Unit
|
public typealias Test2 = suspend kotlin.Int.() -> kotlin.Unit
|
||||||
|
public typealias Test20 = (@A suspend () -> kotlin.Unit)?
|
||||||
public typealias Test3 = () -> kotlin.Unit
|
public typealias Test3 = () -> kotlin.Unit
|
||||||
public typealias Test4 = Action
|
public typealias Test4 = Action
|
||||||
public typealias Test5 = kotlin.collections.List<suspend () -> kotlin.Unit>
|
public typealias Test5 = kotlin.collections.List<suspend () -> kotlin.Unit>
|
||||||
|
|||||||
+5
-1
@@ -6,13 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics
|
package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||||
import org.jetbrains.kotlin.fir.analysis.CheckersComponent
|
import org.jetbrains.kotlin.fir.analysis.CheckersComponent
|
||||||
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.declaration.DeclarationCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.*
|
import org.jetbrains.kotlin.fir.analysis.collectors.components.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
@@ -27,11 +27,13 @@ internal abstract class AbstractFirIdeDiagnosticsCollector(
|
|||||||
init {
|
init {
|
||||||
val declarationCheckers = CheckersFactory.createDeclarationCheckers(useExtendedCheckers)
|
val declarationCheckers = CheckersFactory.createDeclarationCheckers(useExtendedCheckers)
|
||||||
val expressionCheckers = CheckersFactory.createExpressionCheckers(useExtendedCheckers)
|
val expressionCheckers = CheckersFactory.createExpressionCheckers(useExtendedCheckers)
|
||||||
|
val typeCheckers = CheckersFactory.createTypeCheckers(useExtendedCheckers)
|
||||||
|
|
||||||
@Suppress("LeakingThis")
|
@Suppress("LeakingThis")
|
||||||
initializeComponents(
|
initializeComponents(
|
||||||
DeclarationCheckersDiagnosticComponent(this, declarationCheckers),
|
DeclarationCheckersDiagnosticComponent(this, declarationCheckers),
|
||||||
ExpressionCheckersDiagnosticComponent(this, expressionCheckers),
|
ExpressionCheckersDiagnosticComponent(this, expressionCheckers),
|
||||||
|
TypeCheckersDiagnosticComponent(this, typeCheckers),
|
||||||
ErrorNodeDiagnosticCollectorComponent(this),
|
ErrorNodeDiagnosticCollectorComponent(this),
|
||||||
ControlFlowAnalysisDiagnosticComponent(this, declarationCheckers),
|
ControlFlowAnalysisDiagnosticComponent(this, declarationCheckers),
|
||||||
)
|
)
|
||||||
@@ -113,6 +115,8 @@ private object CheckersFactory {
|
|||||||
fun createExpressionCheckers(useExtendedCheckers: Boolean): ExpressionCheckers =
|
fun createExpressionCheckers(useExtendedCheckers: Boolean): ExpressionCheckers =
|
||||||
if (useExtendedCheckers) ExtendedExpressionCheckers else CommonExpressionCheckers
|
if (useExtendedCheckers) ExtendedExpressionCheckers else CommonExpressionCheckers
|
||||||
|
|
||||||
|
fun createTypeCheckers(useExtendedCheckers: Boolean): TypeCheckers = CommonTypeCheckers
|
||||||
|
|
||||||
// TODO hack to have all checkers present in DeclarationCheckers.memberDeclarationCheckers and similar
|
// TODO hack to have all checkers present in DeclarationCheckers.memberDeclarationCheckers and similar
|
||||||
// If use ExtendedDeclarationCheckers directly when DeclarationCheckers.memberDeclarationCheckers will not contain basicDeclarationCheckers
|
// If use ExtendedDeclarationCheckers directly when DeclarationCheckers.memberDeclarationCheckers will not contain basicDeclarationCheckers
|
||||||
@OptIn(SessionConfiguration::class)
|
@OptIn(SessionConfiguration::class)
|
||||||
|
|||||||
Reference in New Issue
Block a user