[FIR] Make reporting of local class diagnostics more consistent with K1
It would be nice to report more appropriate diagnostics at the corresponding places, but right now it's more important to fix greenness-redness problems. Plus, this is already how K1 works. ^KT-59900 Fixed
This commit is contained in:
committed by
Space Team
parent
9b114335fb
commit
0d19942d2c
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
// !DUMP_CFG
|
// !DUMP_CFG
|
||||||
|
|
||||||
val x = object {
|
val x = object {
|
||||||
class Nested {
|
<!NESTED_CLASS_NOT_ALLOWED!>class Nested<!> {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -8,16 +8,16 @@ object A {
|
|||||||
val a = object : Any() {
|
val a = object : Any() {
|
||||||
<!LOCAL_OBJECT_NOT_ALLOWED!>object D<!> {
|
<!LOCAL_OBJECT_NOT_ALLOWED!>object D<!> {
|
||||||
<!LOCAL_OBJECT_NOT_ALLOWED!>object G<!>
|
<!LOCAL_OBJECT_NOT_ALLOWED!>object G<!>
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED, NESTED_CLASS_NOT_ALLOWED!>interface Z<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>interface Z<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface Y<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>interface Y<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun b() {
|
fun b() {
|
||||||
<!LOCAL_OBJECT_NOT_ALLOWED!>object E<!> {
|
<!LOCAL_OBJECT_NOT_ALLOWED!>object E<!> {
|
||||||
<!LOCAL_OBJECT_NOT_ALLOWED!>object F<!>
|
<!LOCAL_OBJECT_NOT_ALLOWED!>object F<!>
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED, NESTED_CLASS_NOT_ALLOWED!>interface M<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>interface M<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface N<!>
|
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface N<!>
|
||||||
@@ -25,7 +25,7 @@ object A {
|
|||||||
val c = object : Any() {
|
val c = object : Any() {
|
||||||
val t = "test"
|
val t = "test"
|
||||||
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface U<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>interface U<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||||
@@ -21,10 +22,12 @@ object FirLocalEntityNotAllowedChecker : FirRegularClassChecker() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val container = context.containingDeclarations.lastOrNull()
|
||||||
|
|
||||||
when {
|
when {
|
||||||
declaration.classKind == ClassKind.OBJECT && !declaration.isCompanion ->
|
declaration.classKind == ClassKind.OBJECT && !declaration.isCompanion ->
|
||||||
reporter.reportOn(declaration.source, FirErrors.LOCAL_OBJECT_NOT_ALLOWED, declaration.name, context)
|
reporter.reportOn(declaration.source, FirErrors.LOCAL_OBJECT_NOT_ALLOWED, declaration.name, context)
|
||||||
declaration.classKind == ClassKind.INTERFACE ->
|
declaration.classKind == ClassKind.INTERFACE && container !is FirClass ->
|
||||||
reporter.reportOn(declaration.source, FirErrors.LOCAL_INTERFACE_NOT_ALLOWED, declaration.name, context)
|
reporter.reportOn(declaration.source, FirErrors.LOCAL_INTERFACE_NOT_ALLOWED, declaration.name, context)
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -6,12 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||||
@@ -22,25 +23,24 @@ object FirNestedClassChecker : FirRegularClassChecker() {
|
|||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
// Local enums / objects / companion objects are handled with different diagnostic codes.
|
// Local enums / objects / companion objects are handled with different diagnostic codes.
|
||||||
if ((declaration.classKind.isSingleton || declaration.classKind == ClassKind.ENUM_CLASS) && declaration.isLocal) return
|
if ((declaration.classKind.isSingleton || declaration.classKind == ClassKind.ENUM_CLASS) && declaration.isLocal) return
|
||||||
val containingDeclaration = context.containingDeclarations.lastOrNull() ?: return
|
val containingDeclaration = context.containingDeclarations.lastOrNull() as? FirClass ?: return
|
||||||
|
|
||||||
when (containingDeclaration) {
|
// Since 1.3, enum entries can contain inner classes only.
|
||||||
is FirRegularClass -> {
|
// Companion objects are reported with code WRONG_MODIFIER_CONTAINING_DECLARATION instead
|
||||||
if (!declaration.isInner && (containingDeclaration.isInner || containingDeclaration.isLocal)) {
|
if (containingDeclaration.classKind == ClassKind.ENUM_ENTRY && !declaration.isInner && !declaration.isCompanion) {
|
||||||
reporter.reportOn(declaration.source, NESTED_CLASS_NOT_ALLOWED, declaration.description, context)
|
reporter.reportOn(declaration.source, NESTED_CLASS_NOT_ALLOWED, declaration.description, context)
|
||||||
}
|
return
|
||||||
}
|
}
|
||||||
is FirClass -> {
|
|
||||||
// Since 1.3, enum entries can contain inner classes only.
|
val containerIsLocal = containingDeclaration.effectiveVisibility == EffectiveVisibility.Local
|
||||||
// Companion objects are reported with code WRONG_MODIFIER_CONTAINING_DECLARATION instead
|
|
||||||
if (containingDeclaration.classKind == ClassKind.ENUM_ENTRY && !declaration.isInner && !declaration.isCompanion) {
|
if (!declaration.isInner && (containingDeclaration.isInner || containerIsLocal || context.isInsideAnonymousObject)) {
|
||||||
reporter.reportOn(declaration.source, NESTED_CLASS_NOT_ALLOWED, declaration.description, context)
|
reporter.reportOn(declaration.source, NESTED_CLASS_NOT_ALLOWED, declaration.description, context)
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val CheckerContext.isInsideAnonymousObject get() = containingDeclarations.any { it is FirAnonymousObject }
|
||||||
|
|
||||||
// Note: here we don't differentiate anonymous object like in FE1.0
|
// Note: here we don't differentiate anonymous object like in FE1.0
|
||||||
// (org.jetbrains.kotlin.resolve.ModifiersChecker.DetailedClassKind) because this case has been ruled out in the first place.
|
// (org.jetbrains.kotlin.resolve.ModifiersChecker.DetailedClassKind) because this case has been ruled out in the first place.
|
||||||
private val FirRegularClass.description: String
|
private val FirRegularClass.description: String
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ enum class Enum {
|
|||||||
|
|
||||||
<!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!>
|
||||||
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED, NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!>
|
||||||
|
|
||||||
<!LOCAL_OBJECT_NOT_ALLOWED!>object TestObject<!>
|
<!LOCAL_OBJECT_NOT_ALLOWED!>object TestObject<!>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ enum class Enum {
|
|||||||
|
|
||||||
<!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!>
|
||||||
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED, NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!>
|
||||||
|
|
||||||
<!LOCAL_OBJECT_NOT_ALLOWED!>object TestObject<!>
|
<!LOCAL_OBJECT_NOT_ALLOWED!>object TestObject<!>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
// KT-6026 Exception on instantiating a nested class in an anonymous object
|
|
||||||
|
|
||||||
val oo = object {
|
|
||||||
// Forbidden in KT-13510
|
|
||||||
class Nested
|
|
||||||
|
|
||||||
fun f1() = Nested(<!TOO_MANY_ARGUMENTS!>11<!>)
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// KT-6026 Exception on instantiating a nested class in an anonymous object
|
// KT-6026 Exception on instantiating a nested class in an anonymous object
|
||||||
|
|
||||||
val oo = object {
|
val oo = object {
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
|
||||||
|
|
||||||
fun foo() {
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface a<!> {}
|
|
||||||
val b = object {
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface c<!> {}
|
|
||||||
}
|
|
||||||
class A {
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED, NESTED_CLASS_NOT_ALLOWED!>interface d<!> {}
|
|
||||||
}
|
|
||||||
val f = {
|
|
||||||
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface e<!> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
|
|||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
class X {
|
|
||||||
val foo = object {
|
|
||||||
class Foo
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
object {
|
|
||||||
class Foo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
class X {
|
class X {
|
||||||
val foo = object {
|
val foo = object {
|
||||||
<!NESTED_CLASS_NOT_ALLOWED!>class Foo<!>
|
<!NESTED_CLASS_NOT_ALLOWED!>class Foo<!>
|
||||||
|
|||||||
Reference in New Issue
Block a user