[FIR] Report ABSTRACT_MEMBER_NOT_IMPLEMENTED_BY_ENUM_ENTRY on enum entries with initializer
#KT-59577 Fixed
This commit is contained in:
committed by
Space Team
parent
ef78d4b95a
commit
44a4498ee5
@@ -0,0 +1,3 @@
|
|||||||
|
/enum.kt:(506,508): error: 'static enum entry E2: EnumClass = object : EnumClass' does not implement abstract members: [fun foo(): Int, val bar: String].
|
||||||
|
|
||||||
|
/enum.kt:(524,526): error: 'static enum entry E3: EnumClass = object : EnumClass' does not implement abstract members: [fun foo(): Int, val bar: String].
|
||||||
+3
-2
@@ -1,3 +1,4 @@
|
|||||||
|
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||||
interface Some
|
interface Some
|
||||||
|
|
||||||
object O1 : Some
|
object O1 : Some
|
||||||
@@ -26,11 +27,11 @@ enum class EnumClass {
|
|||||||
override val bar: String = "a"
|
override val bar: String = "a"
|
||||||
},
|
},
|
||||||
|
|
||||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>E2<!> {
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED_BY_ENUM_ENTRY!>E2<!> {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>E3<!>();
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED_BY_ENUM_ENTRY!>E3<!>();
|
||||||
|
|
||||||
abstract fun foo(): Int
|
abstract fun foo(): Int
|
||||||
abstract val bar: String
|
abstract val bar: String
|
||||||
|
|||||||
+27
-1
@@ -18,13 +18,17 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVISIBLE_ABSTRAC
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER_BY_DELEGATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER_BY_DELEGATION
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED_BY_ENUM_ENTRY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_IMPLEMENTED_BY_INHERITED_VAL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_IMPLEMENTED_BY_INHERITED_VAL
|
||||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
import org.jetbrains.kotlin.fir.delegatedWrapperData
|
import org.jetbrains.kotlin.fir.delegatedWrapperData
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.scopes.MemberWithBaseScope
|
import org.jetbrains.kotlin.fir.scopes.MemberWithBaseScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembersWithBaseScope
|
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembersWithBaseScope
|
||||||
@@ -32,6 +36,8 @@ import org.jetbrains.kotlin.fir.scopes.impl.*
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
|
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
|
||||||
import org.jetbrains.kotlin.util.ImplementationStatus
|
import org.jetbrains.kotlin.util.ImplementationStatus
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
object FirNotImplementedOverrideChecker : FirClassChecker() {
|
object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||||
|
|
||||||
@@ -126,7 +132,18 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
|||||||
val notImplemented = (notImplementedSymbols.firstOrNull { !it.isFromInterfaceOrEnum(context) } ?: notImplementedSymbols.first())
|
val notImplemented = (notImplementedSymbols.firstOrNull { !it.isFromInterfaceOrEnum(context) } ?: notImplementedSymbols.first())
|
||||||
.unwrapFakeOverrides()
|
.unwrapFakeOverrides()
|
||||||
if (notImplemented.isFromInterfaceOrEnum(context)) {
|
if (notImplemented.isFromInterfaceOrEnum(context)) {
|
||||||
reporter.reportOn(source, ABSTRACT_MEMBER_NOT_IMPLEMENTED, classSymbol, notImplemented, context)
|
val containingDeclaration = context.containingDeclarations.lastOrNull()
|
||||||
|
if (declaration.isInitializerOfEnumEntry(containingDeclaration)) {
|
||||||
|
reporter.reportOn(
|
||||||
|
source,
|
||||||
|
ABSTRACT_MEMBER_NOT_IMPLEMENTED_BY_ENUM_ENTRY,
|
||||||
|
containingDeclaration.symbol,
|
||||||
|
notImplementedSymbols,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
reporter.reportOn(source, ABSTRACT_MEMBER_NOT_IMPLEMENTED, classSymbol, notImplemented, context)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
reporter.reportOn(source, ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED, classSymbol, notImplemented, context)
|
reporter.reportOn(source, ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED, classSymbol, notImplemented, context)
|
||||||
}
|
}
|
||||||
@@ -183,6 +200,15 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
private fun FirClass.isInitializerOfEnumEntry(containingDeclaration: FirDeclaration?): Boolean {
|
||||||
|
contract {
|
||||||
|
returns(true) implies (containingDeclaration is FirEnumEntry)
|
||||||
|
}
|
||||||
|
return containingDeclaration is FirEnumEntry &&
|
||||||
|
containingDeclaration.initializer.let { it is FirAnonymousObjectExpression && it.anonymousObject == this }
|
||||||
|
}
|
||||||
|
|
||||||
private fun FirCallableSymbol<*>.isFromInterfaceOrEnum(context: CheckerContext): Boolean =
|
private fun FirCallableSymbol<*>.isFromInterfaceOrEnum(context: CheckerContext): Boolean =
|
||||||
(getContainingClassSymbol(context.session) as? FirRegularClassSymbol)?.let { it.isInterface || it.isEnumClass } == true
|
(getContainingClassSymbol(context.session) as? FirRegularClassSymbol)?.let { it.isInterface || it.isEnumClass } == true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
enum class EnumClass {
|
||||||
|
E1 {
|
||||||
|
override fun foo() = 1
|
||||||
|
override val bar: String = "a"
|
||||||
|
},
|
||||||
|
|
||||||
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED_BY_ENUM_ENTRY!>E2<!> {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract fun foo(): Int
|
||||||
|
abstract val bar: String
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
enum class EnumClass {
|
enum class EnumClass {
|
||||||
E1 {
|
E1 {
|
||||||
override fun foo() = 1
|
override fun foo() = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user