[Test] Add ability to specify applicability of diagnostic to module or file

This commit is contained in:
Dmitriy Novozhilov
2021-01-15 14:54:05 +03:00
committed by TeamCityServer
parent 28cff22cd0
commit 6a7cd0c811
117 changed files with 266 additions and 189 deletions
@@ -9,7 +9,18 @@ import org.jetbrains.kotlin.test.util.joinToArrayString
// --------------------------- Directive declaration ---------------------------
sealed class Directive(val name: String, val description: String) {
enum class DirectiveApplicability(
val forGlobal: Boolean = false,
val forModule: Boolean = false,
val forFile: Boolean = false
) {
Any(forGlobal = true, forModule = true, forFile = true),
Global(forGlobal = true, forModule = true),
Module(forModule = true),
File(forFile = true)
}
sealed class Directive(val name: String, val description: String, val applicability: DirectiveApplicability) {
override fun toString(): String {
return name
}
@@ -17,23 +28,26 @@ sealed class Directive(val name: String, val description: String) {
class SimpleDirective(
name: String,
description: String
) : Directive(name, description)
description: String,
applicability: DirectiveApplicability
) : Directive(name, description, applicability)
class StringDirective(
name: String,
description: String
) : Directive(name, description)
description: String,
applicability: DirectiveApplicability
) : Directive(name, description, applicability)
class ValueDirective<T : Any>(
name: String,
description: String,
applicability: DirectiveApplicability,
val parser: (String) -> T?
) : Directive(name, description)
) : Directive(name, description, applicability)
// --------------------------- Registered directive ---------------------------
abstract class RegisteredDirectives {
abstract class RegisteredDirectives : Iterable<Directive> {
companion object {
val Empty = RegisteredDirectivesImpl(emptyList(), emptyMap(), emptyMap())
}
@@ -78,6 +92,15 @@ class RegisteredDirectivesImpl(
valueDirectives.forEach { (d, v) -> appendLine(" $d: ${v.joinToArrayString()}")}
}
}
@OptIn(ExperimentalStdlibApi::class)
override fun iterator(): Iterator<Directive> {
return buildList {
addAll(simpleDirectives)
addAll(stringDirectives.keys)
addAll(valueDirectives.keys)
}.iterator()
}
}
class ComposedRegisteredDirectives(
@@ -109,6 +132,10 @@ class ComposedRegisteredDirectives(
override fun isEmpty(): Boolean {
return containers.all { it.isEmpty() }
}
override fun iterator(): Iterator<Directive> {
return containers.flatten().iterator()
}
}
// --------------------------- Utils ---------------------------
@@ -20,28 +20,36 @@ abstract class SimpleDirectivesContainer : DirectivesContainer() {
override operator fun get(name: String): Directive? = registeredDirectives[name]
protected fun directive(description: String): DirectiveDelegateProvider<SimpleDirective> {
return DirectiveDelegateProvider { SimpleDirective(it, description) }
protected fun directive(
description: String,
applicability: DirectiveApplicability = DirectiveApplicability.Global
): DirectiveDelegateProvider<SimpleDirective> {
return DirectiveDelegateProvider { SimpleDirective(it, description, applicability) }
}
protected fun stringDirective(description: String): DirectiveDelegateProvider<StringDirective> {
return DirectiveDelegateProvider { StringDirective(it, description) }
protected fun stringDirective(
description: String,
applicability: DirectiveApplicability = DirectiveApplicability.Global
): DirectiveDelegateProvider<StringDirective> {
return DirectiveDelegateProvider { StringDirective(it, description, applicability) }
}
protected inline fun <reified T : Enum<T>> enumDirective(
description: String,
applicability: DirectiveApplicability = DirectiveApplicability.Global,
noinline additionalParser: ((String) -> T?)? = null
): DirectiveDelegateProvider<ValueDirective<T>> {
val possibleValues = enumValues<T>()
val parser: (String) -> T? = { value -> possibleValues.firstOrNull { it.name == value } ?: additionalParser?.invoke(value) }
return DirectiveDelegateProvider { ValueDirective(it, description, parser) }
return DirectiveDelegateProvider { ValueDirective(it, description, applicability, parser) }
}
protected fun <T : Any> valueDirective(
description: String,
applicability: DirectiveApplicability = DirectiveApplicability.Global,
parser: (String) -> T?
): DirectiveDelegateProvider<ValueDirective<T>> {
return DirectiveDelegateProvider { ValueDirective(it, description, parser) }
return DirectiveDelegateProvider { ValueDirective(it, description, applicability, parser) }
}
protected fun registerDirective(directive: Directive) {