FIR checker: introduce PropertyChecker alias
and use it to add diagnostic ININITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION
This commit is contained in:
committed by
Mikhail Glukhikh
parent
db65c787e5
commit
03cb0c3cd1
+1
@@ -27,6 +27,7 @@ fun main(args: Array<String>) {
|
|||||||
generateCheckersComponents(generationPath, declarationPackage, "FirDeclarationChecker") {
|
generateCheckersComponents(generationPath, declarationPackage, "FirDeclarationChecker") {
|
||||||
alias<FirDeclaration>("BasicDeclarationChecker")
|
alias<FirDeclaration>("BasicDeclarationChecker")
|
||||||
alias<FirMemberDeclaration>("MemberDeclarationChecker")
|
alias<FirMemberDeclaration>("MemberDeclarationChecker")
|
||||||
|
alias<FirProperty>("PropertyChecker")
|
||||||
alias<FirRegularClass>("RegularClassChecker")
|
alias<FirRegularClass>("RegularClassChecker")
|
||||||
alias<FirConstructor>("ConstructorChecker")
|
alias<FirConstructor>("ConstructorChecker")
|
||||||
alias<FirFile>("FileChecker")
|
alias<FirFile>("FileChecker")
|
||||||
|
|||||||
+4
@@ -19,6 +19,8 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
|||||||
get() = _basicDeclarationCheckers
|
get() = _basicDeclarationCheckers
|
||||||
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker>
|
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker>
|
||||||
get() = _memberDeclarationCheckers
|
get() = _memberDeclarationCheckers
|
||||||
|
override val propertyCheckers: Set<FirPropertyChecker>
|
||||||
|
get() = _propertyCheckers
|
||||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||||
get() = _regularClassCheckers
|
get() = _regularClassCheckers
|
||||||
override val constructorCheckers: Set<FirConstructorChecker>
|
override val constructorCheckers: Set<FirConstructorChecker>
|
||||||
@@ -32,6 +34,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
|||||||
|
|
||||||
private val _basicDeclarationCheckers: MutableSet<FirBasicDeclarationChecker> = mutableSetOf()
|
private val _basicDeclarationCheckers: MutableSet<FirBasicDeclarationChecker> = mutableSetOf()
|
||||||
private val _memberDeclarationCheckers: MutableSet<FirMemberDeclarationChecker> = mutableSetOf()
|
private val _memberDeclarationCheckers: MutableSet<FirMemberDeclarationChecker> = mutableSetOf()
|
||||||
|
private val _propertyCheckers: MutableSet<FirPropertyChecker> = mutableSetOf()
|
||||||
private val _regularClassCheckers: MutableSet<FirRegularClassChecker> = mutableSetOf()
|
private val _regularClassCheckers: MutableSet<FirRegularClassChecker> = mutableSetOf()
|
||||||
private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf()
|
private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf()
|
||||||
private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf()
|
private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf()
|
||||||
@@ -42,6 +45,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
|||||||
internal fun register(checkers: DeclarationCheckers) {
|
internal fun register(checkers: DeclarationCheckers) {
|
||||||
_basicDeclarationCheckers += checkers.allBasicDeclarationCheckers
|
_basicDeclarationCheckers += checkers.allBasicDeclarationCheckers
|
||||||
_memberDeclarationCheckers += checkers.allMemberDeclarationCheckers
|
_memberDeclarationCheckers += checkers.allMemberDeclarationCheckers
|
||||||
|
_propertyCheckers += checkers.allPropertyCheckers
|
||||||
_regularClassCheckers += checkers.allRegularClassCheckers
|
_regularClassCheckers += checkers.allRegularClassCheckers
|
||||||
_constructorCheckers += checkers.allConstructorCheckers
|
_constructorCheckers += checkers.allConstructorCheckers
|
||||||
_fileCheckers += checkers.allFileCheckers
|
_fileCheckers += checkers.allFileCheckers
|
||||||
|
|||||||
+2
@@ -21,6 +21,7 @@ abstract class DeclarationCheckers {
|
|||||||
|
|
||||||
open val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = emptySet()
|
open val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = emptySet()
|
||||||
open val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = emptySet()
|
open val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = emptySet()
|
||||||
|
open val propertyCheckers: Set<FirPropertyChecker> = emptySet()
|
||||||
open val regularClassCheckers: Set<FirRegularClassChecker> = emptySet()
|
open val regularClassCheckers: Set<FirRegularClassChecker> = emptySet()
|
||||||
open val constructorCheckers: Set<FirConstructorChecker> = emptySet()
|
open val constructorCheckers: Set<FirConstructorChecker> = emptySet()
|
||||||
open val fileCheckers: Set<FirFileChecker> = emptySet()
|
open val fileCheckers: Set<FirFileChecker> = emptySet()
|
||||||
@@ -30,6 +31,7 @@ abstract class DeclarationCheckers {
|
|||||||
|
|
||||||
@CheckersComponentInternal internal val allBasicDeclarationCheckers: Set<FirBasicDeclarationChecker> get() = basicDeclarationCheckers
|
@CheckersComponentInternal internal val allBasicDeclarationCheckers: Set<FirBasicDeclarationChecker> get() = basicDeclarationCheckers
|
||||||
@CheckersComponentInternal internal val allMemberDeclarationCheckers: Set<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + allBasicDeclarationCheckers
|
@CheckersComponentInternal internal val allMemberDeclarationCheckers: Set<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + allBasicDeclarationCheckers
|
||||||
|
@CheckersComponentInternal internal val allPropertyCheckers: Set<FirPropertyChecker> get() = propertyCheckers + allMemberDeclarationCheckers
|
||||||
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> get() = regularClassCheckers + allMemberDeclarationCheckers
|
@CheckersComponentInternal internal val allRegularClassCheckers: Set<FirRegularClassChecker> get() = regularClassCheckers + allMemberDeclarationCheckers
|
||||||
@CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> get() = constructorCheckers + allMemberDeclarationCheckers
|
@CheckersComponentInternal internal val allConstructorCheckers: Set<FirConstructorChecker> get() = constructorCheckers + allMemberDeclarationCheckers
|
||||||
@CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> get() = fileCheckers + allBasicDeclarationCheckers
|
@CheckersComponentInternal internal val allFileCheckers: Set<FirFileChecker> get() = fileCheckers + allBasicDeclarationCheckers
|
||||||
|
|||||||
+2
@@ -14,10 +14,12 @@ import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
|
||||||
typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration>
|
typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration>
|
||||||
typealias FirMemberDeclarationChecker = FirDeclarationChecker<FirMemberDeclaration>
|
typealias FirMemberDeclarationChecker = FirDeclarationChecker<FirMemberDeclaration>
|
||||||
|
typealias FirPropertyChecker = FirDeclarationChecker<FirProperty>
|
||||||
typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
|
typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
|
||||||
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
|
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
|
||||||
typealias FirFileChecker = FirDeclarationChecker<FirFile>
|
typealias FirFileChecker = FirDeclarationChecker<FirFile>
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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.KtNodeTypes
|
||||||
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.extended.report
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||||
|
|
||||||
|
object FirDestructuringDeclarationInitializerChecker : FirPropertyChecker() {
|
||||||
|
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (!declaration.name.isSpecial || declaration.name.asString() != "<destruct>") return
|
||||||
|
val source = declaration.source
|
||||||
|
if (source == null || source.kind is FirFakeSourceElementKind) return
|
||||||
|
if (source.elementType != KtNodeTypes.DESTRUCTURING_DECLARATION) return
|
||||||
|
val needToReport =
|
||||||
|
when (val initializer = declaration.initializer) {
|
||||||
|
null -> true
|
||||||
|
is FirErrorExpression -> (initializer.diagnostic as? ConeSimpleDiagnostic)?.kind == DiagnosticKind.Syntax
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
if (needToReport) {
|
||||||
|
reporter.report(source, FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -22,7 +22,7 @@ class DeclarationCheckersDiagnosticComponent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitProperty(property: FirProperty, data: CheckerContext) {
|
override fun visitProperty(property: FirProperty, data: CheckerContext) {
|
||||||
checkers.memberDeclarationCheckers.check(property, data, reporter)
|
(checkers.memberDeclarationCheckers + checkers.propertyCheckers).check(property, data, reporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
|
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
|
||||||
|
|||||||
@@ -166,6 +166,9 @@ object FirErrors {
|
|||||||
val PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
|
val PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
|
||||||
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
|
val PRIVATE_SETTER_FOR_OPEN_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
|
||||||
|
|
||||||
|
// Destructuring declaration
|
||||||
|
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<FirSourceElement, PsiElement>()
|
||||||
|
|
||||||
// Control flow diagnostics
|
// Control flow diagnostics
|
||||||
val UNINITIALIZED_VARIABLE by error1<FirSourceElement, PsiElement, FirPropertySymbol>()
|
val UNINITIALIZED_VARIABLE by error1<FirSourceElement, PsiElement, FirPropertySymbol>()
|
||||||
val WRONG_INVOCATION_KIND by warning3<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>, EventOccurrencesRange, EventOccurrencesRange>()
|
val WRONG_INVOCATION_KIND by warning3<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>, EventOccurrencesRange, EventOccurrencesRange>()
|
||||||
|
|||||||
+4
@@ -41,6 +41,10 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirInapplicableLateinitChecker,
|
FirInapplicableLateinitChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val propertyCheckers: Set<FirPropertyChecker> = setOf(
|
||||||
|
FirDestructuringDeclarationInitializerChecker,
|
||||||
|
)
|
||||||
|
|
||||||
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
|
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
|
||||||
FirTypeMismatchOnOverrideChecker,
|
FirTypeMismatchOnOverrideChecker,
|
||||||
FirMemberPropertyChecker,
|
FirMemberPropertyChecker,
|
||||||
|
|||||||
+2
-2
@@ -1071,13 +1071,13 @@ class DeclarationsConverter(
|
|||||||
val entries = mutableListOf<FirVariable<*>>()
|
val entries = mutableListOf<FirVariable<*>>()
|
||||||
val source = destructingDeclaration.toFirSourceElement()
|
val source = destructingDeclaration.toFirSourceElement()
|
||||||
var firExpression: FirExpression =
|
var firExpression: FirExpression =
|
||||||
buildErrorExpression(null, ConeSimpleDiagnostic("Destructuring declaration without initializer", DiagnosticKind.Syntax))
|
buildErrorExpression(null, ConeSimpleDiagnostic("Initializer required for destructuring declaration", DiagnosticKind.Syntax))
|
||||||
destructingDeclaration.forEachChildren {
|
destructingDeclaration.forEachChildren {
|
||||||
when (it.tokenType) {
|
when (it.tokenType) {
|
||||||
VAR_KEYWORD -> isVar = true
|
VAR_KEYWORD -> isVar = true
|
||||||
DESTRUCTURING_DECLARATION_ENTRY -> entries += convertDestructingDeclarationEntry(it)
|
DESTRUCTURING_DECLARATION_ENTRY -> entries += convertDestructingDeclarationEntry(it)
|
||||||
else -> if (it.isExpression()) firExpression =
|
else -> if (it.isExpression()) firExpression =
|
||||||
expressionConverter.getAsFirExpression(it, "Destructuring declaration without initializer")
|
expressionConverter.getAsFirExpression(it, "Initializer required for destructuring declaration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,10 +202,13 @@ class RawFirBuilder(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtExpression?.toFirExpression(errorReason: String): FirExpression =
|
private fun KtExpression?.toFirExpression(
|
||||||
|
errorReason: String,
|
||||||
|
kind: DiagnosticKind = DiagnosticKind.ExpressionRequired,
|
||||||
|
): FirExpression =
|
||||||
if (stubMode) buildExpressionStub()
|
if (stubMode) buildExpressionStub()
|
||||||
else convertSafe() ?: buildErrorExpression(
|
else convertSafe() ?: buildErrorExpression(
|
||||||
this?.toFirSourceElement(), ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionRequired),
|
this?.toFirSourceElement(), ConeSimpleDiagnostic(errorReason, kind),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun KtExpression.toFirStatement(errorReason: String): FirStatement =
|
private fun KtExpression.toFirStatement(errorReason: String): FirStatement =
|
||||||
@@ -2061,7 +2064,7 @@ class RawFirBuilder(
|
|||||||
override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Unit): FirElement {
|
override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Unit): FirElement {
|
||||||
val baseVariable = generateTemporaryVariable(
|
val baseVariable = generateTemporaryVariable(
|
||||||
baseSession, multiDeclaration.toFirSourceElement(), "destruct",
|
baseSession, multiDeclaration.toFirSourceElement(), "destruct",
|
||||||
multiDeclaration.initializer.toFirExpression("Destructuring declaration without initializer"),
|
multiDeclaration.initializer.toFirExpression("Initializer required for destructuring declaration", DiagnosticKind.Syntax),
|
||||||
)
|
)
|
||||||
return generateDestructuringBlock(
|
return generateDestructuringBlock(
|
||||||
baseSession,
|
baseSession,
|
||||||
|
|||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
fun useDeclaredVariables() {
|
fun useDeclaredVariables() {
|
||||||
val (<!UNRESOLVED_REFERENCE!>a<!>, <!UNRESOLVED_REFERENCE!>b<!>)
|
<!INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION!>val (<!UNRESOLVED_REFERENCE!>a<!>, <!UNRESOLVED_REFERENCE!>b<!>)<!>
|
||||||
a
|
a
|
||||||
b
|
b
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkersShouldRun() {
|
fun checkersShouldRun() {
|
||||||
val (<!UNRESOLVED_REFERENCE!>@A a<!>, <!UNRESOLVED_REFERENCE!>_<!>)
|
<!INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION!>val (<!UNRESOLVED_REFERENCE!>@A a<!>, <!UNRESOLVED_REFERENCE!>_<!>)<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
annotation class A
|
annotation class A
|
||||||
|
|||||||
Reference in New Issue
Block a user