[FIR] Add generator for checkers aliases and sets of checkers

This commit is contained in:
Dmitriy Novozhilov
2020-09-04 15:20:29 +03:00
parent 4de57fcac2
commit 67604dcb66
22 changed files with 592 additions and 175 deletions
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2020 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.generator
import kotlin.reflect.KClass
import kotlin.reflect.full.superclasses
class CheckersConfiguration(
val aliases: Map<KClass<*>, String>,
val additionalCheckers: MutableMap<String, String>
) {
val parentsMap: Map<KClass<*>, List<KClass<*>>>
init {
val parents: MutableMap<KClass<*>, List<KClass<*>>> = mutableMapOf()
for (firKClass in aliases.keys) {
val directParents = mutableListOf<KClass<*>>()
bfs(
firKClass,
childrenExtractor = { it.superclasses }
) {
if (it in aliases) {
directParents += it
false
} else {
true
}
}
parents[firKClass] = directParents
}
parentsMap = parents
}
}
private fun <T> bfs(start: T, childrenExtractor: (T) -> Collection<T>, process: (T) -> Boolean) {
val queue = ArrayDeque<T>()
val visited = mutableSetOf<T>()
val levels = mutableMapOf(start to 0)
queue.addLast(start)
var levelToStop: Int? = null
while (queue.isNotEmpty()) {
val element = queue.removeFirst()
if (!visited.add(element)) continue
val level = levels.getValue(element)
if (levelToStop != null && level > levelToStop) continue
val shouldContinue = if (level > 0) process(element) else true
if (shouldContinue) {
val children = childrenExtractor(element)
for (child in children) {
levels[child] = level + 1
queue.addLast(child)
}
} else {
levelToStop = level
}
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2020 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.generator
import org.jetbrains.kotlin.fir.FirElement
import java.io.File
import kotlin.reflect.KClass
class CheckersConfigurator {
private val registeredAliases: MutableMap<KClass<*>, String> = LinkedHashMap()
private val additionalCheckers: MutableMap<String, String> = LinkedHashMap()
inline fun <reified T : FirElement> alias(name: String) {
alias(T::class, name)
}
fun alias(kClass: KClass<out FirElement>, name: String) {
val realName = name.takeIf { it.startsWith("Fir") } ?: "Fir$name"
registeredAliases[kClass] = realName
}
fun additional(fieldName: String, classFqn: String) {
additionalCheckers[fieldName] = classFqn
}
fun build(): CheckersConfiguration {
return CheckersConfiguration(registeredAliases, additionalCheckers)
}
}
fun generateCheckersComponents(
generationPath: File,
packageName: String,
abstractCheckerName: String,
init: CheckersConfigurator.() -> Unit
) {
val configuration = CheckersConfigurator().apply(init).build()
Generator(configuration, generationPath, packageName, abstractCheckerName).generate()
}
@@ -0,0 +1,186 @@
/*
* Copyright 2010-2020 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.generator
import org.jetbrains.kotlin.fir.tree.generator.printer.*
import java.io.File
private typealias Alias = String
private typealias Fqn = String
private const val CHECKERS_COMPONENT_INTERNAL_ANNOTATION = "@CheckersComponentInternal"
private const val CHECKERS_COMPONENT_INTERNAL_FQN = "org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal"
class Generator(
private val configuration: CheckersConfiguration,
generationPath: File,
private val packageName: String,
private val abstractCheckerName: String
) {
private val generationPath: File
init {
var path = generationPath
packageName.split(".").forEach {
path = path.resolve(it)
}
path.mkdirs()
this.generationPath = path
}
private fun generateAliases() {
val filename = "${abstractCheckerName}Aliases.kt"
generationPath.resolve(filename).useSmartPrinter {
printPackageAndCopyright()
printGeneratedMessage()
configuration.aliases.keys
.mapNotNull { it.qualifiedName }
.sorted()
.forEach { println("import $it") }
println()
for ((kClass, alias) in configuration.aliases) {
println("typealias $alias = $abstractCheckerName<${kClass.simpleName}>")
}
}
}
private fun generateAbstractCheckersComponent() {
val filename = "${checkersComponentName}.kt"
generationPath.resolve(filename).useSmartPrinter {
printPackageAndCopyright()
printImports()
printGeneratedMessage()
println("abstract class $checkersComponentName {")
withIndent {
println("companion object {")
withIndent {
println("val EMPTY: $checkersComponentName = object : $checkersComponentName() {}")
}
println("}")
println()
for (alias in configuration.aliases.values) {
println("open ${alias.valDeclaration} = emptySet()")
}
println()
for ((fieldName, classFqn) in configuration.additionalCheckers) {
val fieldClassName = classFqn.simpleName
println("open val $fieldName: ${fieldClassName.setType} = emptySet()")
}
if (configuration.additionalCheckers.isNotEmpty()) {
println()
}
for ((kClass, alias) in configuration.aliases) {
print("$CHECKERS_COMPONENT_INTERNAL_ANNOTATION internal val ${alias.allFieldName}: ${alias.setType} get() = ${alias.fieldName}")
for (parent in configuration.parentsMap.getValue(kClass)) {
val parentAlias = configuration.aliases.getValue(parent)
print(" + ${parentAlias.allFieldName}")
}
println()
}
}
println("}")
}
}
private fun generateComposedComponent() {
val composedComponentName = "Composed$checkersComponentName"
val filename = "${composedComponentName}.kt"
generationPath.resolve(filename).useSmartPrinter {
printPackageAndCopyright()
printImports()
printGeneratedMessage()
println("internal class $composedComponentName : $checkersComponentName() {")
withIndent {
// public overrides
for (alias in configuration.aliases.values) {
println("override ${alias.valDeclaration}")
withIndent {
println("get() = _${alias.fieldName}")
}
}
for ((fieldName, classFqn) in configuration.additionalCheckers) {
println("override val $fieldName: ${classFqn.simpleName.setType}")
withIndent {
println("get() = _$fieldName")
}
}
println()
// private mutable delegates
for (alias in configuration.aliases.values) {
println("private val _${alias.fieldName}: ${alias.mutableSetType} = mutableSetOf()")
}
for ((fieldName, classFqn) in configuration.additionalCheckers) {
println("private val _$fieldName: ${classFqn.simpleName.mutableSetType} = mutableSetOf()")
}
println()
// register function
println(CHECKERS_COMPONENT_INTERNAL_ANNOTATION)
println("internal fun register(checkers: $checkersComponentName) {")
withIndent {
for (alias in configuration.aliases.values) {
println("_${alias.fieldName} += checkers.${alias.allFieldName}")
}
for (fieldName in configuration.additionalCheckers.keys) {
println("_$fieldName += checkers.$fieldName")
}
}
println("}")
}
println("}")
}
}
private fun SmartPrinter.printPackageAndCopyright() {
printCopyright()
println("package $packageName")
println()
}
@OptIn(ExperimentalStdlibApi::class)
private fun SmartPrinter.printImports() {
val imports = buildList {
addAll(configuration.additionalCheckers.values)
add(CHECKERS_COMPONENT_INTERNAL_FQN)
}.sorted()
for (fqn in imports) {
println("import $fqn")
}
println()
}
private val Alias.valDeclaration: String
get() = "val $fieldName: $setType"
private val Alias.fieldName: String
get() = removePrefix("Fir").decapitalize() + "s"
private val Alias.allFieldName: String
get() = "all${fieldName.capitalize()}"
private val Alias.setType: String
get() = "Set<$this>"
private val Alias.mutableSetType: String
get() = "MutableSet<$this>"
private val Fqn.simpleName: String
get() = this.split(".").last()
private val checkersComponentName = abstractCheckerName.removePrefix("Fir") + "s"
fun generate() {
generateAliases()
generateAbstractCheckersComponent()
generateComposedComponent()
}
}
@@ -5,4 +5,49 @@
package org.jetbrains.kotlin.fir.checkers.generator
fun main() {}
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import java.io.File
fun main(args: Array<String>) {
val generationPath = args.firstOrNull()?.let { File(it) } ?: File("compiler/fir/checkers/gen").absoluteFile
val expressionPackage = "org.jetbrains.kotlin.fir.analysis.checkers.expression"
generateCheckersComponents(generationPath, expressionPackage, "FirExpressionChecker") {
alias<FirStatement>("BasicExpressionChecker")
alias<FirQualifiedAccessExpression>("QualifiedAccessChecker")
alias<FirFunctionCall>("FunctionCallChecker")
alias<FirVariableAssignment>("VariableAssignmentChecker")
}
val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration"
generateCheckersComponents(generationPath, declarationPackage, "FirDeclarationChecker") {
alias<FirDeclaration>("BasicDeclarationChecker")
alias<FirMemberDeclaration>("MemberDeclarationChecker")
alias<FirRegularClass>("RegularClassChecker")
alias<FirConstructor>("ConstructorChecker")
alias<FirFile>("FileChecker")
additional(
fieldName = "controlFlowAnalyserCheckers",
classFqn = "org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker"
)
additional(
fieldName = "variableAssignmentCfaBasedCheckers",
classFqn = "org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker"
)
}
}
/*
* Stages:
* 1. associate aliases with fir statements
* 2. build inheritance hierarchy for all mentioned fir elements
* 3. generate aliases
* 4. generate abstract "DeclarationCheckers"
* 5. generate "ComposedDeclarationCheckers" with OptIn annotation
*/
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2020 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.analysis.CheckersComponentInternal
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
internal class ComposedDeclarationCheckers : DeclarationCheckers() {
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker>
get() = _basicDeclarationCheckers
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker>
get() = _memberDeclarationCheckers
override val regularClassCheckers: Set<FirRegularClassChecker>
get() = _regularClassCheckers
override val constructorCheckers: Set<FirConstructorChecker>
get() = _constructorCheckers
override val fileCheckers: Set<FirFileChecker>
get() = _fileCheckers
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker>
get() = _controlFlowAnalyserCheckers
override val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker>
get() = _variableAssignmentCfaBasedCheckers
private val _basicDeclarationCheckers: MutableSet<FirBasicDeclarationChecker> = mutableSetOf()
private val _memberDeclarationCheckers: MutableSet<FirMemberDeclarationChecker> = mutableSetOf()
private val _regularClassCheckers: MutableSet<FirRegularClassChecker> = mutableSetOf()
private val _constructorCheckers: MutableSet<FirConstructorChecker> = mutableSetOf()
private val _fileCheckers: MutableSet<FirFileChecker> = mutableSetOf()
private val _controlFlowAnalyserCheckers: MutableSet<FirControlFlowChecker> = mutableSetOf()
private val _variableAssignmentCfaBasedCheckers: MutableSet<AbstractFirPropertyInitializationChecker> = mutableSetOf()
@CheckersComponentInternal
internal fun register(checkers: DeclarationCheckers) {
_basicDeclarationCheckers += checkers.allBasicDeclarationCheckers
_memberDeclarationCheckers += checkers.allMemberDeclarationCheckers
_regularClassCheckers += checkers.allRegularClassCheckers
_constructorCheckers += checkers.allConstructorCheckers
_fileCheckers += checkers.allFileCheckers
_controlFlowAnalyserCheckers += checkers.controlFlowAnalyserCheckers
_variableAssignmentCfaBasedCheckers += checkers.variableAssignmentCfaBasedCheckers
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2020 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.analysis.CheckersComponentInternal
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class DeclarationCheckers {
companion object {
val EMPTY: DeclarationCheckers = object : DeclarationCheckers() {}
}
open val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = emptySet()
open val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = emptySet()
open val regularClassCheckers: Set<FirRegularClassChecker> = emptySet()
open val constructorCheckers: Set<FirConstructorChecker> = emptySet()
open val fileCheckers: Set<FirFileChecker> = emptySet()
open val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = emptySet()
open val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker> = emptySet()
@CheckersComponentInternal internal val allBasicDeclarationCheckers: Set<FirBasicDeclarationChecker> get() = basicDeclarationCheckers
@CheckersComponentInternal internal val allMemberDeclarationCheckers: Set<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + allBasicDeclarationCheckers
@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
}
@@ -0,0 +1,23 @@
/*
* Copyright 2010-2020 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
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
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.FirRegularClass
typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration>
typealias FirMemberDeclarationChecker = FirDeclarationChecker<FirMemberDeclaration>
typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
typealias FirFileChecker = FirDeclarationChecker<FirFile>
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2020 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.expression
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
internal class ComposedExpressionCheckers : ExpressionCheckers() {
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = _basicExpressionCheckers
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
get() = _qualifiedAccessCheckers
override val functionCallCheckers: Set<FirFunctionCallChecker>
get() = _functionCallCheckers
override val variableAssignmentCheckers: Set<FirVariableAssignmentChecker>
get() = _variableAssignmentCheckers
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
private val _qualifiedAccessCheckers: MutableSet<FirQualifiedAccessChecker> = mutableSetOf()
private val _functionCallCheckers: MutableSet<FirFunctionCallChecker> = mutableSetOf()
private val _variableAssignmentCheckers: MutableSet<FirVariableAssignmentChecker> = mutableSetOf()
@CheckersComponentInternal
internal fun register(checkers: ExpressionCheckers) {
_basicExpressionCheckers += checkers.allBasicExpressionCheckers
_qualifiedAccessCheckers += checkers.allQualifiedAccessCheckers
_functionCallCheckers += checkers.allFunctionCallCheckers
_variableAssignmentCheckers += checkers.allVariableAssignmentCheckers
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2020 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.expression
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class ExpressionCheckers {
companion object {
val EMPTY: ExpressionCheckers = object : ExpressionCheckers() {}
}
open val basicExpressionCheckers: Set<FirBasicExpressionChecker> = emptySet()
open val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = emptySet()
open val functionCallCheckers: Set<FirFunctionCallChecker> = emptySet()
open val variableAssignmentCheckers: Set<FirVariableAssignmentChecker> = emptySet()
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> get() = basicExpressionCheckers
@CheckersComponentInternal internal val allQualifiedAccessCheckers: Set<FirQualifiedAccessChecker> get() = qualifiedAccessCheckers + allBasicExpressionCheckers
@CheckersComponentInternal internal val allFunctionCallCheckers: Set<FirFunctionCallChecker> get() = functionCallCheckers + allQualifiedAccessCheckers
@CheckersComponentInternal internal val allVariableAssignmentCheckers: Set<FirVariableAssignmentChecker> get() = variableAssignmentCheckers + allBasicExpressionCheckers
}
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2020 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.expression
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
typealias FirBasicExpressionChecker = FirExpressionChecker<FirStatement>
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccessExpression>
typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
typealias FirVariableAssignmentChecker = FirExpressionChecker<FirVariableAssignment>
@@ -8,12 +8,13 @@ package org.jetbrains.kotlin.fir.analysis
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.SessionConfiguration
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
@RequiresOptIn
annotation class CheckersComponentInternal
class CheckersComponent : FirSessionComponent {
val declarationCheckers: DeclarationCheckers get() = _declarationCheckers
private val _declarationCheckers = ComposedDeclarationCheckers()
@@ -22,11 +23,13 @@ class CheckersComponent : FirSessionComponent {
private val _expressionCheckers = ComposedExpressionCheckers()
@SessionConfiguration
@OptIn(CheckersComponentInternal::class)
fun register(checkers: DeclarationCheckers) {
_declarationCheckers.register(checkers)
}
@SessionConfiguration
@OptIn(CheckersComponentInternal::class)
fun register(checkers: ExpressionCheckers) {
_expressionCheckers.register(checkers)
}
@@ -39,61 +42,3 @@ class CheckersComponent : FirSessionComponent {
}
val FirSession.checkersComponent: CheckersComponent by FirSession.sessionComponentAccessor()
private class ComposedDeclarationCheckers : DeclarationCheckers() {
override val fileCheckers: List<FirFileChecker>
get() = _fileCheckers
override val declarationCheckers: List<FirBasicDeclarationChecker>
get() = _declarationCheckers
override val memberDeclarationCheckers: List<FirMemberDeclarationChecker>
get() = _memberDeclarationCheckers
override val regularClassCheckers: List<FirRegularClassChecker>
get() = _regularClassCheckers
override val constructorCheckers: List<FirConstructorChecker>
get() = _constructorCheckers
override val controlFlowAnalyserCheckers: List<FirControlFlowChecker>
get() = _controlFlowAnalyserCheckers
override val variableAssignmentCfaBasedCheckers: List<AbstractFirPropertyInitializationChecker>
get() = _variableAssignmentCfaBasedCheckers
private val _fileCheckers: MutableList<FirFileChecker> = mutableListOf()
private val _declarationCheckers: MutableList<FirBasicDeclarationChecker> = mutableListOf()
private val _memberDeclarationCheckers: MutableList<FirMemberDeclarationChecker> = mutableListOf()
private val _regularClassCheckers: MutableList<FirRegularClassChecker> = mutableListOf()
private val _constructorCheckers: MutableList<FirConstructorChecker> = mutableListOf()
private val _controlFlowAnalyserCheckers: MutableList<FirControlFlowChecker> = mutableListOf()
private val _variableAssignmentCfaBasedCheckers: MutableList<AbstractFirPropertyInitializationChecker> = mutableListOf()
fun register(checkers: DeclarationCheckers) {
_fileCheckers += checkers.allFileCheckers
_declarationCheckers += checkers.declarationCheckers
_memberDeclarationCheckers += checkers.allMemberDeclarationCheckers
_regularClassCheckers += checkers.allRegularClassCheckers
_constructorCheckers += checkers.allConstructorCheckers
_controlFlowAnalyserCheckers += checkers.controlFlowAnalyserCheckers
_variableAssignmentCfaBasedCheckers += checkers.variableAssignmentCfaBasedCheckers
}
}
private class ComposedExpressionCheckers : ExpressionCheckers() {
override val expressionCheckers: List<FirBasicExpressionChecker>
get() = _expressionCheckers
override val qualifiedAccessCheckers: List<FirQualifiedAccessChecker>
get() = _qualifiedAccessCheckers
override val functionCallCheckers: List<FirFunctionCallChecker>
get() = _functionCallCheckers
override val variableAssignmentCheckers: List<FirVariableAssignmentChecker>
get() = _variableAssignmentCheckers
private val _expressionCheckers: MutableList<FirBasicExpressionChecker> = mutableListOf()
private val _qualifiedAccessCheckers: MutableList<FirQualifiedAccessChecker> = mutableListOf()
private val _functionCallCheckers: MutableList<FirFunctionCallChecker> = mutableListOf()
private val _variableAssignmentCheckers: MutableList<FirVariableAssignmentChecker> = mutableListOf()
fun register(checkers: ExpressionCheckers) {
_expressionCheckers += checkers.allExpressionCheckers
_qualifiedAccessCheckers += checkers.allQualifiedAccessCheckers
_functionCallCheckers += checkers.allFunctionCallCheckers
_variableAssignmentCheckers += checkers.variableAssignmentCheckers
}
}
@@ -1,28 +0,0 @@
/*
* Copyright 2010-2020 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.analysis.cfa.AbstractFirPropertyInitializationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
abstract class DeclarationCheckers {
companion object {
val EMPTY: DeclarationCheckers = object : DeclarationCheckers() {}
}
open val fileCheckers: List<FirFileChecker> = emptyList()
open val declarationCheckers: List<FirBasicDeclarationChecker> = emptyList()
open val memberDeclarationCheckers: List<FirMemberDeclarationChecker> = emptyList()
open val regularClassCheckers: List<FirRegularClassChecker> = emptyList()
open val constructorCheckers: List<FirConstructorChecker> = emptyList()
open val controlFlowAnalyserCheckers: List<FirControlFlowChecker> = emptyList()
open val variableAssignmentCfaBasedCheckers: List<AbstractFirPropertyInitializationChecker> = emptyList()
internal val allFileCheckers: List<FirFileChecker> get() = fileCheckers + declarationCheckers
internal val allMemberDeclarationCheckers: List<FirMemberDeclarationChecker> get() = memberDeclarationCheckers + declarationCheckers
internal val allRegularClassCheckers: List<FirRegularClassChecker> get() = regularClassCheckers + allMemberDeclarationCheckers
internal val allConstructorCheckers: List<FirConstructorChecker> get() = constructorCheckers + allMemberDeclarationCheckers
}
@@ -12,9 +12,3 @@ import org.jetbrains.kotlin.fir.declarations.*
abstract class FirDeclarationChecker<in D : FirDeclaration> {
abstract fun check(declaration: D, context: CheckerContext, reporter: DiagnosticReporter)
}
typealias FirFileChecker = FirDeclarationChecker<FirFile>
typealias FirBasicDeclarationChecker = FirDeclarationChecker<FirDeclaration>
typealias FirMemberDeclarationChecker = FirDeclarationChecker<FirMemberDeclaration>
typealias FirRegularClassChecker = FirDeclarationChecker<FirRegularClass>
typealias FirConstructorChecker = FirDeclarationChecker<FirConstructor>
@@ -1,21 +0,0 @@
/*
* Copyright 2010-2020 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.expression
abstract class ExpressionCheckers {
companion object {
val EMPTY: ExpressionCheckers = object : ExpressionCheckers() {}
}
open val expressionCheckers: List<FirBasicExpressionChecker> = emptyList()
open val qualifiedAccessCheckers: List<FirQualifiedAccessChecker> = emptyList()
open val functionCallCheckers: List<FirFunctionCallChecker> = emptyList()
open val variableAssignmentCheckers: List<FirVariableAssignmentChecker> = emptyList()
internal val allExpressionCheckers get() = expressionCheckers
internal val allQualifiedAccessCheckers get() = qualifiedAccessCheckers + allExpressionCheckers
internal val allFunctionCallCheckers get() = functionCallCheckers + allQualifiedAccessCheckers
}
@@ -7,16 +7,8 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
abstract class FirExpressionChecker<in E : FirStatement> {
abstract fun check(expression: E, context: CheckerContext, reporter: DiagnosticReporter)
}
typealias FirBasicExpressionChecker = FirExpressionChecker<FirStatement>
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccessExpression>
typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
typealias FirVariableAssignmentChecker = FirExpressionChecker<FirVariableAssignment>
@@ -42,34 +42,34 @@ class DeclarationCheckersDiagnosticComponent(
}
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) {
checkers.declarationCheckers.check(anonymousFunction, data, reporter)
checkers.basicDeclarationCheckers.check(anonymousFunction, data, reporter)
}
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: CheckerContext) {
checkers.declarationCheckers.check(propertyAccessor, data, reporter)
checkers.basicDeclarationCheckers.check(propertyAccessor, data, reporter)
}
override fun visitValueParameter(valueParameter: FirValueParameter, data: CheckerContext) {
checkers.declarationCheckers.check(valueParameter, data, reporter)
checkers.basicDeclarationCheckers.check(valueParameter, data, reporter)
}
override fun visitTypeParameter(typeParameter: FirTypeParameter, data: CheckerContext) {
checkers.declarationCheckers.check(typeParameter, data, reporter)
checkers.basicDeclarationCheckers.check(typeParameter, data, reporter)
}
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: CheckerContext) {
checkers.declarationCheckers.check(enumEntry, data, reporter)
checkers.basicDeclarationCheckers.check(enumEntry, data, reporter)
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: CheckerContext) {
checkers.declarationCheckers.check(anonymousObject, data, reporter)
checkers.basicDeclarationCheckers.check(anonymousObject, data, reporter)
}
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: CheckerContext) {
checkers.declarationCheckers.check(anonymousInitializer, data, reporter)
checkers.basicDeclarationCheckers.check(anonymousInitializer, data, reporter)
}
private fun <D : FirDeclaration> List<FirDeclarationChecker<D>>.check(
private fun <D : FirDeclaration> Collection<FirDeclarationChecker<D>>.check(
declaration: D,
context: CheckerContext,
reporter: DiagnosticReporter
@@ -16,15 +16,15 @@ class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollect
private val checkers = session.checkersComponent.expressionCheckers
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: CheckerContext) {
checkers.expressionCheckers.check(typeOperatorCall, data, reporter)
checkers.basicExpressionCheckers.check(typeOperatorCall, data, reporter)
}
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: CheckerContext) {
checkers.expressionCheckers.check(constExpression, data, reporter)
checkers.basicExpressionCheckers.check(constExpression, data, reporter)
}
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: CheckerContext) {
checkers.expressionCheckers.check(annotationCall, data, reporter)
checkers.basicExpressionCheckers.check(annotationCall, data, reporter)
}
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: CheckerContext) {
@@ -40,54 +40,58 @@ class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollect
}
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: CheckerContext) {
checkers.expressionCheckers.check(thisReceiverExpression, data, reporter)
checkers.basicExpressionCheckers.check(thisReceiverExpression, data, reporter)
}
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: CheckerContext) {
checkers.expressionCheckers.check(resolvedQualifier, data, reporter)
checkers.basicExpressionCheckers.check(resolvedQualifier, data, reporter)
}
override fun visitWhenExpression(whenExpression: FirWhenExpression, data: CheckerContext) {
checkers.expressionCheckers.check(whenExpression, data, reporter)
checkers.basicExpressionCheckers.check(whenExpression, data, reporter)
}
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: CheckerContext) {
checkers.expressionCheckers.check(binaryLogicExpression, data, reporter)
checkers.basicExpressionCheckers.check(binaryLogicExpression, data, reporter)
}
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: CheckerContext) {
checkers.expressionCheckers.check(arrayOfCall, data, reporter)
checkers.basicExpressionCheckers.check(arrayOfCall, data, reporter)
}
override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: CheckerContext) {
checkers.expressionCheckers.check(stringConcatenationCall, data, reporter)
checkers.basicExpressionCheckers.check(stringConcatenationCall, data, reporter)
}
override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: CheckerContext) {
checkers.expressionCheckers.check(checkNotNullCall, data, reporter)
checkers.basicExpressionCheckers.check(checkNotNullCall, data, reporter)
}
override fun visitTryExpression(tryExpression: FirTryExpression, data: CheckerContext) {
checkers.expressionCheckers.check(tryExpression, data, reporter)
checkers.basicExpressionCheckers.check(tryExpression, data, reporter)
}
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: CheckerContext) {
checkers.expressionCheckers.check(classReferenceExpression, data, reporter)
checkers.basicExpressionCheckers.check(classReferenceExpression, data, reporter)
}
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: CheckerContext) {
checkers.expressionCheckers.check(getClassCall, data, reporter)
checkers.basicExpressionCheckers.check(getClassCall, data, reporter)
}
override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: CheckerContext) {
checkers.expressionCheckers.check(equalityOperatorCall, data, reporter)
checkers.basicExpressionCheckers.check(equalityOperatorCall, data, reporter)
}
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) {
checkers.variableAssignmentCheckers.check(variableAssignment, data, reporter)
}
private fun <E : FirStatement> List<FirExpressionChecker<E>>.check(expression: E, context: CheckerContext, reporter: DiagnosticReporter) {
private fun <E : FirStatement> Collection<FirExpressionChecker<E>>.check(
expression: E,
context: CheckerContext,
reporter: DiagnosticReporter
) {
for (checker in this) {
checker.check(expression, context, reporter)
}
@@ -13,9 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
object CommonDeclarationCheckers : DeclarationCheckers() {
override val fileCheckers: List<FirFileChecker> = listOf()
override val declarationCheckers: List<FirBasicDeclarationChecker> = listOf(
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = setOf(
FirAnnotationClassDeclarationChecker,
FirModifierChecker,
FirManyCompanionObjectsChecker,
@@ -26,7 +24,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirConflictingProjectionChecker,
)
override val memberDeclarationCheckers: List<FirMemberDeclarationChecker> = listOf(
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = setOf(
FirInfixFunctionDeclarationChecker,
FirExposedVisibilityDeclarationChecker,
FirCommonConstructorDelegationIssuesChecker,
@@ -42,20 +40,20 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirInapplicableLateinitChecker,
)
override val regularClassCheckers: List<FirRegularClassChecker> = listOf(
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
FirTypeMismatchOnOverrideChecker,
)
override val constructorCheckers: List<FirConstructorChecker> = listOf(
override val constructorCheckers: Set<FirConstructorChecker> = setOf(
FirConstructorAllowedChecker,
)
override val controlFlowAnalyserCheckers: List<FirControlFlowChecker> = listOf(
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = setOf(
FirCallsEffectAnalyzer,
FirReturnsImpliesAnalyzer
FirReturnsImpliesAnalyzer,
)
override val variableAssignmentCfaBasedCheckers: List<AbstractFirPropertyInitializationChecker> = listOf(
FirPropertyInitializationAnalyzer
override val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker> = setOf(
FirPropertyInitializationAnalyzer,
)
}
@@ -9,8 +9,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirSealedClassCons
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
object CommonExpressionCheckers : ExpressionCheckers() {
override val expressionCheckers: List<FirBasicExpressionChecker> = listOf()
override val qualifiedAccessCheckers: List<FirQualifiedAccessChecker> = listOf(
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = setOf(
FirSuperNotAvailableChecker,
FirNotASupertypeChecker,
FirSuperclassNotAccessibleFromInterfaceChecker,
@@ -21,5 +20,5 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirTypeArgumentsNotAllowedExpressionChecker,
FirSealedClassConstructorCallChecker,
)
override val functionCallCheckers: List<FirFunctionCallChecker> = listOf()
override val functionCallCheckers: Set<FirFunctionCallChecker> = setOf()
}
@@ -8,25 +8,29 @@ package org.jetbrains.kotlin.fir.checkers
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.extended.*
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
object ExtendedDeclarationCheckers : DeclarationCheckers() {
override val declarationCheckers = listOf(
override val basicDeclarationCheckers: Set<FirBasicDeclarationChecker> = setOf(
RedundantVisibilityModifierChecker,
RedundantReturnUnitType
RedundantReturnUnitType,
)
override val memberDeclarationCheckers = listOf(
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = setOf(
RedundantModalityModifierChecker,
RedundantExplicitTypeChecker,
RedundantSetterParameterTypeChecker
RedundantSetterParameterTypeChecker,
)
override val variableAssignmentCfaBasedCheckers: List<AbstractFirPropertyInitializationChecker> = listOf(
override val variableAssignmentCfaBasedCheckers: Set<AbstractFirPropertyInitializationChecker> = setOf(
CanBeValChecker,
)
override val controlFlowAnalyserCheckers: List<FirControlFlowChecker> = listOf(
UnusedChecker
override val controlFlowAnalyserCheckers: Set<FirControlFlowChecker> = setOf(
UnusedChecker,
)
}
@@ -12,18 +12,18 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirVariableAssignme
import org.jetbrains.kotlin.fir.analysis.checkers.extended.*
object ExtendedExpressionCheckers : ExpressionCheckers() {
override val expressionCheckers: List<FirBasicExpressionChecker> = listOf(
override val basicExpressionCheckers: Set<FirBasicExpressionChecker> = setOf(
ArrayEqualityCanBeReplacedWithEquals,
RedundantSingleExpressionStringTemplateChecker,
EmptyRangeChecker
EmptyRangeChecker,
)
override val variableAssignmentCheckers: List<FirVariableAssignmentChecker> = listOf(
CanBeReplacedWithOperatorAssignmentChecker
override val variableAssignmentCheckers: Set<FirVariableAssignmentChecker> = setOf(
CanBeReplacedWithOperatorAssignmentChecker,
)
override val qualifiedAccessCheckers: List<FirQualifiedAccessChecker> = listOf(
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = setOf(
RedundantCallOfConversionMethod,
UselessCallOnNotNullChecker
UselessCallOnNotNullChecker,
)
}
@@ -17,6 +17,6 @@ class AllOpenAdditionalCheckers(session: FirSession) : FirAdditionalCheckersExte
get() = AllOpenPluginKey
override val declarationCheckers: DeclarationCheckers = object : DeclarationCheckers() {
override val memberDeclarationCheckers: List<FirMemberDeclarationChecker> = listOf(DummyNameChecker)
override val memberDeclarationCheckers: Set<FirMemberDeclarationChecker> = setOf(DummyNameChecker)
}
}
}