FIR: implement checker for open members
Specifically, 1. NON_FINAL_MEMBER_IN_FINAL_CLASS 2. NON_FINAL_MEMBER_IN_OBJECT
This commit is contained in:
committed by
Mikhail Glukhikh
parent
3e9ff3ecda
commit
6b453d9b23
Vendored
+1
-1
@@ -47,7 +47,7 @@ class FinalDerived : Base() {
|
|||||||
// Redundant final
|
// Redundant final
|
||||||
override <!REDUNDANT_MODALITY_MODIFIER!>final<!> fun bar() {}
|
override <!REDUNDANT_MODALITY_MODIFIER!>final<!> fun bar() {}
|
||||||
// Non-final member in final class
|
// Non-final member in final class
|
||||||
override open val gav = 13
|
override <!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> val gav = 13
|
||||||
}
|
}
|
||||||
// Open
|
// Open
|
||||||
open class OpenDerived : Base() {
|
open class OpenDerived : Base() {
|
||||||
|
|||||||
+2
@@ -243,6 +243,8 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
parameter<FirMemberDeclaration>("overridingDeclaration")
|
parameter<FirMemberDeclaration>("overridingDeclaration")
|
||||||
parameter<FirMemberDeclaration>("overriddenDeclaration")
|
parameter<FirMemberDeclaration>("overriddenDeclaration")
|
||||||
}
|
}
|
||||||
|
val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.OPEN_MODIFIER)
|
||||||
|
val NON_FINAL_MEMBER_IN_OBJECT by warning<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.OPEN_MODIFIER)
|
||||||
}
|
}
|
||||||
|
|
||||||
val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") {
|
val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") {
|
||||||
|
|||||||
@@ -176,6 +176,8 @@ object FirErrors {
|
|||||||
val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||||
val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||||
val VAR_OVERRIDDEN_BY_VAL by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
val VAR_OVERRIDDEN_BY_VAL by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
||||||
|
val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.OPEN_MODIFIER)
|
||||||
|
val NON_FINAL_MEMBER_IN_OBJECT by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.OPEN_MODIFIER)
|
||||||
|
|
||||||
// Redeclarations
|
// Redeclarations
|
||||||
val MANY_COMPANION_OBJECTS by error0<FirSourceElement, PsiElement>()
|
val MANY_COMPANION_OBJECTS by error0<FirSourceElement, PsiElement>()
|
||||||
|
|||||||
+6
@@ -5,9 +5,12 @@
|
|||||||
|
|
||||||
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.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
@@ -123,3 +126,6 @@ internal fun checkPropertyInitializer(
|
|||||||
private val FirProperty.hasAccessorImplementation: Boolean
|
private val FirProperty.hasAccessorImplementation: Boolean
|
||||||
get() = (getter !is FirDefaultPropertyAccessor && getter?.hasBody == true) ||
|
get() = (getter !is FirDefaultPropertyAccessor && getter?.hasBody == true) ||
|
||||||
(setter !is FirDefaultPropertyAccessor && setter?.hasBody == true)
|
(setter !is FirDefaultPropertyAccessor && setter?.hasBody == true)
|
||||||
|
|
||||||
|
|
||||||
|
internal val FirClass<*>.canHaveOpenMembers: Boolean get() = modality() != Modality.FINAL || classKind == ClassKind.ENUM_CLASS
|
||||||
|
|||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirModifierList.Companion.getModifierList
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.isOpen
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
|
object FirOpenMemberChecker : FirClassChecker() {
|
||||||
|
override fun check(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (declaration.canHaveOpenMembers) return
|
||||||
|
for (memberDeclaration in declaration.declarations) {
|
||||||
|
if (memberDeclaration !is FirCallableMemberDeclaration<*> ||
|
||||||
|
// Marking a constructor `open` is an error covered by diagnostic code WRONG_MODIFIER_TARGET
|
||||||
|
memberDeclaration is FirConstructor
|
||||||
|
) continue
|
||||||
|
val source = memberDeclaration.source ?: continue
|
||||||
|
if (memberDeclaration.isOpen || (source.hasOpenModifierInSource && source.shouldReportOpenFromSource)) {
|
||||||
|
if (declaration.classKind == ClassKind.OBJECT) {
|
||||||
|
reporter.reportOn(source, FirErrors.NON_FINAL_MEMBER_IN_OBJECT, context)
|
||||||
|
} else {
|
||||||
|
reporter.reportOn(source, FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val FirSourceElement.hasOpenModifierInSource: Boolean get() = getModifierList()?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true
|
||||||
|
private val FirSourceElement.shouldReportOpenFromSource: Boolean
|
||||||
|
get() = when (kind) {
|
||||||
|
FirRealSourceElementKind,
|
||||||
|
FirFakeSourceElementKind.PropertyFromParameter -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -99,6 +99,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OB
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_OBJECT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MEMBER_FUNCTION_NO_BODY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_MEMBER_FUNCTION_NO_BODY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED
|
||||||
@@ -394,6 +396,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
FQ_NAMES_IN_TYPES,
|
FQ_NAMES_IN_TYPES,
|
||||||
FQ_NAMES_IN_TYPES
|
FQ_NAMES_IN_TYPES
|
||||||
)
|
)
|
||||||
|
map.put(NON_FINAL_MEMBER_IN_FINAL_CLASS, "'open' has no effect in a final class")
|
||||||
|
map.put(NON_FINAL_MEMBER_IN_OBJECT, "'open' has no effect in an object")
|
||||||
map.put(
|
map.put(
|
||||||
GENERIC_THROWABLE_SUBCLASS,
|
GENERIC_THROWABLE_SUBCLASS,
|
||||||
"Subclass of 'Throwable' may not have type parameters"
|
"Subclass of 'Throwable' may not have type parameters"
|
||||||
|
|||||||
+1
@@ -39,6 +39,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
override val classCheckers: Set<FirClassChecker> = setOf(
|
override val classCheckers: Set<FirClassChecker> = setOf(
|
||||||
FirOverrideChecker,
|
FirOverrideChecker,
|
||||||
FirThrowableSubclassChecker,
|
FirThrowableSubclassChecker,
|
||||||
|
FirOpenMemberChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
|
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ inline class A4(var x: Int)
|
|||||||
inline class A5(val x: Int, val y: Int)
|
inline class A5(val x: Int, val y: Int)
|
||||||
inline class A6(x: Int, val y: Int)
|
inline class A6(x: Int, val y: Int)
|
||||||
inline class A7(vararg val x: Int)
|
inline class A7(vararg val x: Int)
|
||||||
inline class A8(open val x: Int)
|
inline class A8(<!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> val x: Int)
|
||||||
inline class A9(final val x: Int)
|
inline class A9(final val x: Int)
|
||||||
|
|
||||||
class B1 {
|
class B1 {
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ abstract class A() {
|
|||||||
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {}
|
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {}
|
||||||
|
|
||||||
open var r: String
|
open var r: String
|
||||||
get
|
get
|
||||||
abstract protected set
|
abstract protected set
|
||||||
}
|
}
|
||||||
|
|
||||||
final interface T {}
|
final interface T {}
|
||||||
|
|
||||||
class FinalClass() {
|
class FinalClass() {
|
||||||
open fun foo() {}
|
<!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> fun foo() {}
|
||||||
val i: Int = 1
|
val i: Int = 1
|
||||||
open get(): Int = field
|
open get(): Int = field
|
||||||
var j: Int = 1
|
var j: Int = 1
|
||||||
@@ -32,13 +32,13 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var
|
|||||||
|
|
||||||
//Check illegal modifier in constructor parameters
|
//Check illegal modifier in constructor parameters
|
||||||
class IllegalModifiers1(
|
class IllegalModifiers1(
|
||||||
<!INCOMPATIBLE_MODIFIERS!>in<!>
|
<!INCOMPATIBLE_MODIFIERS!>in<!>
|
||||||
<!INCOMPATIBLE_MODIFIERS!>out<!>
|
<!INCOMPATIBLE_MODIFIERS!>out<!>
|
||||||
reified
|
reified
|
||||||
enum
|
enum
|
||||||
private
|
private
|
||||||
const
|
const
|
||||||
a: Int)
|
a: Int)
|
||||||
|
|
||||||
//Check multiple illegal modifiers in constructor
|
//Check multiple illegal modifiers in constructor
|
||||||
class IllegalModifiers2(<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> a: Int)
|
class IllegalModifiers2(<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> a: Int)
|
||||||
@@ -53,26 +53,26 @@ class IllegalModifiers4(val a: Int, @annotated("a text") protected vararg v: Int
|
|||||||
//Check illegal modifiers for functions and catch block
|
//Check illegal modifiers for functions and catch block
|
||||||
abstract class IllegalModifiers5() {
|
abstract class IllegalModifiers5() {
|
||||||
|
|
||||||
//Check illegal modifier in function parameter
|
//Check illegal modifier in function parameter
|
||||||
abstract fun foo(public a: Int, vararg v: String)
|
abstract fun foo(public a: Int, vararg v: String)
|
||||||
|
|
||||||
//Check multiple illegal modifiers in function parameter
|
//Check multiple illegal modifiers in function parameter
|
||||||
abstract fun bar(public abstract a: Int, vararg v: String)
|
abstract fun bar(public abstract a: Int, vararg v: String)
|
||||||
|
|
||||||
//Check annotations with illegal modifiers
|
|
||||||
abstract fun baz(@annotated("a text") public abstract a: Int)
|
|
||||||
|
|
||||||
private fun qux() {
|
|
||||||
|
|
||||||
//Check illegal modifier in catch block
|
|
||||||
try {} catch (<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> reified enum public e: Exception) {}
|
|
||||||
|
|
||||||
//Check multiple illegal modifiers in catch block
|
|
||||||
try {} catch (<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> reified enum abstract public e: Exception) {}
|
|
||||||
|
|
||||||
//Check annotations with illegal modifiers
|
//Check annotations with illegal modifiers
|
||||||
try {} catch (@annotated("a text") abstract public e: Exception) {}
|
abstract fun baz(@annotated("a text") public abstract a: Int)
|
||||||
}
|
|
||||||
|
private fun qux() {
|
||||||
|
|
||||||
|
//Check illegal modifier in catch block
|
||||||
|
try {} catch (<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> reified enum public e: Exception) {}
|
||||||
|
|
||||||
|
//Check multiple illegal modifiers in catch block
|
||||||
|
try {} catch (<!INCOMPATIBLE_MODIFIERS!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> reified enum abstract public e: Exception) {}
|
||||||
|
|
||||||
|
//Check annotations with illegal modifiers
|
||||||
|
try {} catch (@annotated("a text") abstract public e: Exception) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check illegal modifiers on anonymous initializers
|
//Check illegal modifiers on anonymous initializers
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ abstract class A() {
|
|||||||
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {}
|
<!INCOMPATIBLE_MODIFIERS!>final<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun h() {}
|
||||||
|
|
||||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>open var r: String<!>
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>open var r: String<!>
|
||||||
get
|
get
|
||||||
<!WRONG_MODIFIER_TARGET!>abstract<!> protected set
|
<!WRONG_MODIFIER_TARGET!>abstract<!> protected set
|
||||||
}
|
}
|
||||||
|
|
||||||
<!WRONG_MODIFIER_TARGET!>final<!> interface T {}
|
<!WRONG_MODIFIER_TARGET!>final<!> interface T {}
|
||||||
@@ -32,13 +32,13 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var
|
|||||||
|
|
||||||
//Check illegal modifier in constructor parameters
|
//Check illegal modifier in constructor parameters
|
||||||
class IllegalModifiers1(
|
class IllegalModifiers1(
|
||||||
<!WRONG_MODIFIER_TARGET!>in<!>
|
<!WRONG_MODIFIER_TARGET!>in<!>
|
||||||
<!INCOMPATIBLE_MODIFIERS!>out<!>
|
<!INCOMPATIBLE_MODIFIERS!>out<!>
|
||||||
<!WRONG_MODIFIER_TARGET!>reified<!>
|
<!WRONG_MODIFIER_TARGET!>reified<!>
|
||||||
<!WRONG_MODIFIER_TARGET!>enum<!>
|
<!WRONG_MODIFIER_TARGET!>enum<!>
|
||||||
<!WRONG_MODIFIER_TARGET!>private<!>
|
<!WRONG_MODIFIER_TARGET!>private<!>
|
||||||
<!WRONG_MODIFIER_TARGET!>const<!>
|
<!WRONG_MODIFIER_TARGET!>const<!>
|
||||||
<!UNUSED_PARAMETER!>a<!>: Int)
|
<!UNUSED_PARAMETER!>a<!>: Int)
|
||||||
|
|
||||||
//Check multiple illegal modifiers in constructor
|
//Check multiple illegal modifiers in constructor
|
||||||
class IllegalModifiers2(<!WRONG_MODIFIER_TARGET!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> <!UNUSED_PARAMETER!>a<!>: Int)
|
class IllegalModifiers2(<!WRONG_MODIFIER_TARGET!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> <!UNUSED_PARAMETER!>a<!>: Int)
|
||||||
@@ -53,26 +53,26 @@ class IllegalModifiers4(val a: Int, @annotated("a text") <!WRONG_MODIFIER_TARGET
|
|||||||
//Check illegal modifiers for functions and catch block
|
//Check illegal modifiers for functions and catch block
|
||||||
abstract class IllegalModifiers5() {
|
abstract class IllegalModifiers5() {
|
||||||
|
|
||||||
//Check illegal modifier in function parameter
|
//Check illegal modifier in function parameter
|
||||||
abstract fun foo(<!WRONG_MODIFIER_TARGET!>public<!> a: Int, vararg v: String)
|
abstract fun foo(<!WRONG_MODIFIER_TARGET!>public<!> a: Int, vararg v: String)
|
||||||
|
|
||||||
//Check multiple illegal modifiers in function parameter
|
//Check multiple illegal modifiers in function parameter
|
||||||
abstract fun bar(<!WRONG_MODIFIER_TARGET!>public<!> <!WRONG_MODIFIER_TARGET!>abstract<!> a: Int, vararg v: String)
|
abstract fun bar(<!WRONG_MODIFIER_TARGET!>public<!> <!WRONG_MODIFIER_TARGET!>abstract<!> a: Int, vararg v: String)
|
||||||
|
|
||||||
//Check annotations with illegal modifiers
|
|
||||||
abstract fun baz(@annotated("a text") <!WRONG_MODIFIER_TARGET!>public<!> <!WRONG_MODIFIER_TARGET!>abstract<!> a: Int)
|
|
||||||
|
|
||||||
private fun qux() {
|
|
||||||
|
|
||||||
//Check illegal modifier in catch block
|
|
||||||
try {} catch (<!WRONG_MODIFIER_TARGET!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> <!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
|
|
||||||
|
|
||||||
//Check multiple illegal modifiers in catch block
|
|
||||||
try {} catch (<!WRONG_MODIFIER_TARGET!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> <!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>abstract<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
|
|
||||||
|
|
||||||
//Check annotations with illegal modifiers
|
//Check annotations with illegal modifiers
|
||||||
try {} catch (@annotated("a text") <!WRONG_MODIFIER_TARGET!>abstract<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
|
abstract fun baz(@annotated("a text") <!WRONG_MODIFIER_TARGET!>public<!> <!WRONG_MODIFIER_TARGET!>abstract<!> a: Int)
|
||||||
}
|
|
||||||
|
private fun qux() {
|
||||||
|
|
||||||
|
//Check illegal modifier in catch block
|
||||||
|
try {} catch (<!WRONG_MODIFIER_TARGET!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> <!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
|
||||||
|
|
||||||
|
//Check multiple illegal modifiers in catch block
|
||||||
|
try {} catch (<!WRONG_MODIFIER_TARGET!>in<!> <!INCOMPATIBLE_MODIFIERS!>out<!> <!WRONG_MODIFIER_TARGET!>reified<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>abstract<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
|
||||||
|
|
||||||
|
//Check annotations with illegal modifiers
|
||||||
|
try {} catch (@annotated("a text") <!WRONG_MODIFIER_TARGET!>abstract<!> <!WRONG_MODIFIER_TARGET!>public<!> e: Exception) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check illegal modifiers on anonymous initializers
|
//Check illegal modifiers on anonymous initializers
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
object Obj {
|
|
||||||
fun foo() {}
|
|
||||||
|
|
||||||
open fun bar() {}
|
|
||||||
|
|
||||||
var x: Int = 0
|
|
||||||
|
|
||||||
open var y: Int = 1
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
object Obj {
|
object Obj {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Foo {
|
class Foo {
|
||||||
open fun openFoo() {}
|
<!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> fun openFoo() {}
|
||||||
fun finalFoo() {}
|
fun finalFoo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ value class A6(x: Int, val y: Int)
|
|||||||
@JvmInline
|
@JvmInline
|
||||||
value class A7(vararg val x: Int)
|
value class A7(vararg val x: Int)
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class A8(open val x: Int)
|
value class A8(<!NON_FINAL_MEMBER_IN_FINAL_CLASS!>open<!> val x: Int)
|
||||||
@JvmInline
|
@JvmInline
|
||||||
value class A9(final val x: Int)
|
value class A9(final val x: Int)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -54,6 +54,6 @@ interface E {
|
|||||||
interface F {
|
interface F {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
open val a = 3
|
<!NON_FINAL_MEMBER_IN_OBJECT!>open<!> val a = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -16,7 +16,7 @@ object B: A() {
|
|||||||
|
|
||||||
@JvmStatic final override fun c() {}
|
@JvmStatic final override fun c() {}
|
||||||
|
|
||||||
@JvmStatic open fun d() {}
|
@JvmStatic <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> fun d() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class C {
|
class C {
|
||||||
@@ -28,6 +28,6 @@ class C {
|
|||||||
|
|
||||||
@JvmStatic final override fun c() {}
|
@JvmStatic final override fun c() {}
|
||||||
|
|
||||||
@JvmStatic open fun d() {}
|
@JvmStatic <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> fun d() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -30,7 +30,7 @@ class A {
|
|||||||
|
|
||||||
@JvmStatic override val base1: Int = 0
|
@JvmStatic override val base1: Int = 0
|
||||||
|
|
||||||
@JvmStatic open fun f() {}
|
@JvmStatic <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> fun f() {}
|
||||||
|
|
||||||
override val base2: Int = 0
|
override val base2: Int = 0
|
||||||
@JvmStatic get
|
@JvmStatic get
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ class A {
|
|||||||
|
|
||||||
@JvmStatic override val base1: Int = 0
|
@JvmStatic override val base1: Int = 0
|
||||||
|
|
||||||
@JvmStatic open fun f() {}
|
@JvmStatic <!NON_FINAL_MEMBER_IN_OBJECT!>open<!> fun f() {}
|
||||||
|
|
||||||
override val base2: Int = 0
|
override val base2: Int = 0
|
||||||
@JvmStatic get
|
@JvmStatic get
|
||||||
|
|||||||
+12
@@ -723,6 +723,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS) { firDiagnostic ->
|
||||||
|
NonFinalMemberInFinalClassImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.NON_FINAL_MEMBER_IN_OBJECT) { firDiagnostic ->
|
||||||
|
NonFinalMemberInObjectImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.MANY_COMPANION_OBJECTS) { firDiagnostic ->
|
add(FirErrors.MANY_COMPANION_OBJECTS) { firDiagnostic ->
|
||||||
ManyCompanionObjectsImpl(
|
ManyCompanionObjectsImpl(
|
||||||
firDiagnostic as FirPsiDiagnostic<*>,
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
|||||||
+8
@@ -515,6 +515,14 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val overriddenDeclaration: KtSymbol
|
abstract val overriddenDeclaration: KtSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NonFinalMemberInFinalClass : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||||
|
override val diagnosticClass get() = NonFinalMemberInFinalClass::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class NonFinalMemberInObject : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||||
|
override val diagnosticClass get() = NonFinalMemberInObject::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ManyCompanionObjects : KtFirDiagnostic<PsiElement>() {
|
abstract class ManyCompanionObjects : KtFirDiagnostic<PsiElement>() {
|
||||||
override val diagnosticClass get() = ManyCompanionObjects::class
|
override val diagnosticClass get() = ManyCompanionObjects::class
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -822,6 +822,20 @@ internal class VarOverriddenByValImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class NonFinalMemberInFinalClassImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NonFinalMemberInFinalClass(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NonFinalMemberInObjectImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.NonFinalMemberInObject(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class ManyCompanionObjectsImpl(
|
internal class ManyCompanionObjectsImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
Reference in New Issue
Block a user