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") {
|
||||
alias<FirDeclaration>("BasicDeclarationChecker")
|
||||
alias<FirMemberDeclaration>("MemberDeclarationChecker")
|
||||
alias<FirProperty>("PropertyChecker")
|
||||
alias<FirRegularClass>("RegularClassChecker")
|
||||
alias<FirConstructor>("ConstructorChecker")
|
||||
alias<FirFile>("FileChecker")
|
||||
|
||||
+4
@@ -19,6 +19,8 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
get() = _basicDeclarationCheckers
|
||||
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker>
|
||||
get() = _memberDeclarationCheckers
|
||||
override val propertyCheckers: Set<FirPropertyChecker>
|
||||
get() = _propertyCheckers
|
||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||
get() = _regularClassCheckers
|
||||
override val constructorCheckers: Set<FirConstructorChecker>
|
||||
@@ -32,6 +34,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
|
||||
private val _basicDeclarationCheckers: MutableSet<FirBasicDeclarationChecker> = mutableSetOf()
|
||||
private val _memberDeclarationCheckers: MutableSet<FirMemberDeclarationChecker> = mutableSetOf()
|
||||
private val _propertyCheckers: MutableSet<FirPropertyChecker> = mutableSetOf()
|
||||
private val _regularClassCheckers: MutableSet<FirRegularClassChecker> = mutableSetOf()
|
||||
private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf()
|
||||
private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf()
|
||||
@@ -42,6 +45,7 @@ internal class ComposedDeclarationCheckers : DeclarationCheckers() {
|
||||
internal fun register(checkers: DeclarationCheckers) {
|
||||
_basicDeclarationCheckers += checkers.allBasicDeclarationCheckers
|
||||
_memberDeclarationCheckers += checkers.allMemberDeclarationCheckers
|
||||
_propertyCheckers += checkers.allPropertyCheckers
|
||||
_regularClassCheckers += checkers.allRegularClassCheckers
|
||||
_constructorCheckers += checkers.allConstructorCheckers
|
||||
_fileCheckers += checkers.allFileCheckers
|
||||
|
||||
+2
@@ -21,6 +21,7 @@ abstract class DeclarationCheckers {
|
||||
|
||||
open val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = emptySet()
|
||||
open val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = emptySet()
|
||||
open val propertyCheckers: Set<FirPropertyChecker> = emptySet()
|
||||
open val regularClassCheckers: Set<FirRegularClassChecker> = emptySet()
|
||||
open val constructorCheckers: Set<FirConstructorChecker> = 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 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 allConstructorCheckers: Set<FirConstructorChecker> get() = constructorCheckers + allMemberDeclarationCheckers
|
||||
@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.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration>
|
||||
typealias FirMemberDeclarationChecker = FirDeclarationChecker<FirMemberDeclaration>
|
||||
typealias FirPropertyChecker = FirDeclarationChecker<FirProperty>
|
||||
typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
|
||||
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
|
||||
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) {
|
||||
checkers.memberDeclarationCheckers.check(property, data, reporter)
|
||||
(checkers.memberDeclarationCheckers + checkers.propertyCheckers).check(property, data, reporter)
|
||||
}
|
||||
|
||||
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_OPEN_PROPERTY by error1<FirSourceElement, PsiElement, FirPropertyAccessorSymbol>()
|
||||
|
||||
// Destructuring declaration
|
||||
val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0<FirSourceElement, PsiElement>()
|
||||
|
||||
// Control flow diagnostics
|
||||
val UNINITIALIZED_VARIABLE by error1<FirSourceElement, PsiElement, FirPropertySymbol>()
|
||||
val WRONG_INVOCATION_KIND by warning3<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>, EventOccurrencesRange, EventOccurrencesRange>()
|
||||
|
||||
+4
@@ -41,6 +41,10 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirInapplicableLateinitChecker,
|
||||
)
|
||||
|
||||
override val propertyCheckers: Set<FirPropertyChecker> = setOf(
|
||||
FirDestructuringDeclarationInitializerChecker,
|
||||
)
|
||||
|
||||
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
|
||||
FirTypeMismatchOnOverrideChecker,
|
||||
FirMemberPropertyChecker,
|
||||
|
||||
+2
-2
@@ -1071,13 +1071,13 @@ class DeclarationsConverter(
|
||||
val entries = mutableListOf<FirVariable<*>>()
|
||||
val source = destructingDeclaration.toFirSourceElement()
|
||||
var firExpression: FirExpression =
|
||||
buildErrorExpression(null, ConeSimpleDiagnostic("Destructuring declaration without initializer", DiagnosticKind.Syntax))
|
||||
buildErrorExpression(null, ConeSimpleDiagnostic("Initializer required for destructuring declaration", DiagnosticKind.Syntax))
|
||||
destructingDeclaration.forEachChildren {
|
||||
when (it.tokenType) {
|
||||
VAR_KEYWORD -> isVar = true
|
||||
DESTRUCTURING_DECLARATION_ENTRY -> entries += convertDestructingDeclarationEntry(it)
|
||||
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()
|
||||
else convertSafe() ?: buildErrorExpression(
|
||||
this?.toFirSourceElement(), ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionRequired),
|
||||
this?.toFirSourceElement(), ConeSimpleDiagnostic(errorReason, kind),
|
||||
)
|
||||
|
||||
private fun KtExpression.toFirStatement(errorReason: String): FirStatement =
|
||||
@@ -2061,7 +2064,7 @@ class RawFirBuilder(
|
||||
override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Unit): FirElement {
|
||||
val baseVariable = generateTemporaryVariable(
|
||||
baseSession, multiDeclaration.toFirSourceElement(), "destruct",
|
||||
multiDeclaration.initializer.toFirExpression("Destructuring declaration without initializer"),
|
||||
multiDeclaration.initializer.toFirExpression("Initializer required for destructuring declaration", DiagnosticKind.Syntax),
|
||||
)
|
||||
return generateDestructuringBlock(
|
||||
baseSession,
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
fun useDeclaredVariables() {
|
||||
val (<!UNRESOLVED_REFERENCE!>a<!>, <!UNRESOLVED_REFERENCE!>b<!>)
|
||||
<!INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION!>val (<!UNRESOLVED_REFERENCE!>a<!>, <!UNRESOLVED_REFERENCE!>b<!>)<!>
|
||||
a
|
||||
b
|
||||
}
|
||||
|
||||
fun checkersShouldRun() {
|
||||
val (<!UNRESOLVED_REFERENCE!>@A a<!>, <!UNRESOLVED_REFERENCE!>_<!>)
|
||||
<!INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION!>val (<!UNRESOLVED_REFERENCE!>@A a<!>, <!UNRESOLVED_REFERENCE!>_<!>)<!>
|
||||
}
|
||||
|
||||
annotation class A
|
||||
|
||||
Reference in New Issue
Block a user