[FIR] Support 4 diagnostics for pairs of modifiers

In particular, this commit includes:
* Attempt to abstract access to FirSourceElement via FirModifier
* Add more visit functions to DeclarationCheckersDiagnosticComponent
* Add messages+factories for 4 modifier-related errors and warnings
* Introduce FirModifierChecker
This commit is contained in:
FenstonSingel
2020-03-27 02:10:26 +03:00
committed by Mikhail Glukhikh
parent 311a91af79
commit b7d8e879a6
42 changed files with 656 additions and 122 deletions
@@ -0,0 +1,31 @@
class A<<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> T> { }
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>public<!> class B
<!INCOMPATIBLE_MODIFIERS!>protected<!> <!INCOMPATIBLE_MODIFIERS!>internal<!> class C
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> class D
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> class E
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>sealed<!> class F
<!INCOMPATIBLE_MODIFIERS!>open<!> <!INCOMPATIBLE_MODIFIERS!>sealed<!> class G
inline fun foo(
<!INCOMPATIBLE_MODIFIERS!>crossinline<!> <!INCOMPATIBLE_MODIFIERS!>noinline<!> first: () -> Unit,
second: () -> Unit
) { }
<!INCOMPATIBLE_MODIFIERS, REDUNDANT_MODIFIER!>open<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> <!INCOMPATIBLE_MODIFIERS!>data<!> class H(val i: Int)
<!INCOMPATIBLE_MODIFIERS!>sealed<!> <!INCOMPATIBLE_MODIFIERS!>data<!> class I(val i: Int)
<!INCOMPATIBLE_MODIFIERS!>inline<!> <!INCOMPATIBLE_MODIFIERS!>data<!> class J(val i: Int)
abstract class K {
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>open<!> val i1: Int = 0
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> val i2: Int
}
private open class L : K()
private abstract class M : K()
class X {
<!INCOMPATIBLE_MODIFIERS!>inner<!> <!INCOMPATIBLE_MODIFIERS!>data<!> class Y(val i: Int)
<!INCOMPATIBLE_MODIFIERS!>sealed<!> <!INCOMPATIBLE_MODIFIERS!>inner<!> class Z
}
@@ -0,0 +1,147 @@
FILE: incompatibleModifiers.kt
public final class A<out T> : R|kotlin/Any| {
public constructor<out T>(): R|A<T>| {
super<R|kotlin/Any|>()
}
}
private final class B : R|kotlin/Any| {
public[private] constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
protected final class C : R|kotlin/Any| {
public[protected] constructor(): R|C| {
super<R|kotlin/Any|>()
}
}
public final class D : R|kotlin/Any| {
public constructor(): R|D| {
super<R|kotlin/Any|>()
}
}
public final class E : R|kotlin/Any| {
public constructor(): R|E| {
super<R|kotlin/Any|>()
}
}
public final class F : R|kotlin/Any| {
private constructor(): R|F| {
super<R|kotlin/Any|>()
}
}
public sealed class G : R|kotlin/Any| {
private constructor(): R|G| {
super<R|kotlin/Any|>()
}
}
public final inline fun foo(crossinline noinline first: R|() -> kotlin/Unit|, second: R|() -> kotlin/Unit|): R|kotlin/Unit| {
}
public abstract data class H : R|kotlin/Any| {
public constructor(i: R|kotlin/Int|): R|H| {
super<R|kotlin/Any|>()
}
public final val i: R|kotlin/Int| = R|<local>/i|
public get(): R|kotlin/Int|
public final fun component1(): R|kotlin/Int| {
^component1 this@R|/H|.R|/H.i|
}
public final fun copy(i: R|kotlin/Int| = this@R|/H|.R|/H.i|): R|H| {
}
}
public sealed data class I : R|kotlin/Any| {
private constructor(i: R|kotlin/Int|): R|I| {
super<R|kotlin/Any|>()
}
public final val i: R|kotlin/Int| = R|<local>/i|
public get(): R|kotlin/Int|
public final fun component1(): R|kotlin/Int| {
^component1 this@R|/I|.R|/I.i|
}
public final fun copy(i: R|kotlin/Int| = this@R|/I|.R|/I.i|): R|I| {
}
}
public final data inline class J : R|kotlin/Any| {
public constructor(i: R|kotlin/Int|): R|J| {
super<R|kotlin/Any|>()
}
public final val i: R|kotlin/Int| = R|<local>/i|
public get(): R|kotlin/Int|
public final fun component1(): R|kotlin/Int| {
^component1 this@R|/J|.R|/J.i|
}
public final fun copy(i: R|kotlin/Int| = this@R|/J|.R|/J.i|): R|J| {
}
}
public abstract class K : R|kotlin/Any| {
public constructor(): R|K| {
super<R|kotlin/Any|>()
}
private open val i1: R|kotlin/Int| = Int(0)
private get(): R|kotlin/Int|
private abstract val i2: R|kotlin/Int|
private get(): R|kotlin/Int|
}
private open class L : R|K| {
public[private] constructor(): R|L| {
super<R|K|>()
}
}
private abstract class M : R|K| {
public[private] constructor(): R|M| {
super<R|K|>()
}
}
public final class X : R|kotlin/Any| {
public constructor(): R|X| {
super<R|kotlin/Any|>()
}
public final inner data class Y : R|kotlin/Any| {
public constructor(i: R|kotlin/Int|): R|X.Y| {
super<R|kotlin/Any|>()
}
public final val i: R|kotlin/Int| = R|<local>/i|
public get(): R|kotlin/Int|
public final fun component1(): R|kotlin/Int| {
^component1 this@R|/X.Y|.R|/X.Y.i|
}
public final fun copy(i: R|kotlin/Int| = this@R|/X.Y|.R|/X.Y.i|): R|X.Y| {
}
}
public sealed inner class Z : R|kotlin/Any| {
private constructor(): R|X.Z| {
super<R|kotlin/Any|>()
}
}
}
@@ -0,0 +1,2 @@
<!REDUNDANT_MODIFIER!>open<!> abstract class A
<!REDUNDANT_MODIFIER!>abstract<!> sealed class B
@@ -0,0 +1,13 @@
FILE: redundantModifier.kt
public abstract class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
public sealed class B : R|kotlin/Any| {
private constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
@@ -0,0 +1,17 @@
open <!REPEATED_MODIFIER!>open<!> class A
internal <!REPEATED_MODIFIER!>internal<!> object B
enum <!REPEATED_MODIFIER!>enum<!> class C {
VALUE1, VALUE2;
protected <!REPEATED_MODIFIER!>protected<!> companion object {
private <!REPEATED_MODIFIER!>private<!> val D = 5
}
inline <!REPEATED_MODIFIER!>inline<!> fun foo(f: (Int) -> Int) = f(8)
}
open class E(private <!REPEATED_MODIFIER!>private<!> val int: Int = 5) {
protected <!REPEATED_MODIFIER!>protected<!> var double = int + 8.0
}
@@ -0,0 +1,54 @@
FILE: repeatedModifier.kt
public open class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
}
internal final object B : R|kotlin/Any| {
private constructor(): R|B| {
super<R|kotlin/Any|>()
}
}
public final enum class C : R|kotlin/Enum<C>| {
private constructor(): R|C| {
super<R|kotlin/Enum<C>|>()
}
public final static enum entry VALUE1: R|C|
public final static enum entry VALUE2: R|C|
protected final companion object Companion : R|kotlin/Any| {
private constructor(): R|C.Companion| {
super<R|kotlin/Any|>()
}
private final val D: R|kotlin/Int| = Int(5)
private get(): R|kotlin/Int|
}
public final inline fun foo(f: R|(kotlin/Int) -> kotlin/Int|): R|kotlin/Int| {
^foo R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(Int(8))
}
public final static fun values(): R|kotlin/Array<C>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|C| {
}
}
public open class E : R|kotlin/Any| {
public constructor(int: R|kotlin/Int| = Int(5)): R|E| {
super<R|kotlin/Any|>()
}
private final val int: R|kotlin/Int| = R|<local>/int|
private get(): R|kotlin/Int|
protected final var double: R|kotlin/Double| = R|<local>/int|.R|kotlin/Int.plus|(Double(8.0))
protected get(): R|kotlin/Double|
protected set(value: R|kotlin/Double|): R|kotlin/Unit|
}