FIR checker: report VIRTUAL_MEMBER_HIDDEN

This commit is contained in:
Tianyu Geng
2021-05-24 13:29:32 -07:00
committed by Mikhail Glukhikh
parent d3dfb33f89
commit 32f55a2269
30 changed files with 195 additions and 99 deletions
@@ -8,7 +8,7 @@ open class A {
class B : A() {
override fun foo(): B = this
fun bar(): B = this // Ambiguity, no override here (really it's just "missing override" and no ambiguity)
fun <!VIRTUAL_MEMBER_HIDDEN!>bar<!>(): B = this // Missing 'override'
override fun buz(p: B): B = this //No override as B not :> A
fun test() {
@@ -44,7 +44,7 @@ public <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class LightClassWrapper<!> : Light(),
}
public abstract class Light : Field, TypeParametersOwner {
fun getTypeParameters() = listOf()
fun <!VIRTUAL_MEMBER_HIDDEN!>getTypeParameters<!>() = listOf()
}
public interface Field : Named
@@ -14,7 +14,7 @@ public class A {
class B : A() {
override fun foo(): B = this
fun bar(): B = this // Here we should have "missing override" but no ambiguity
fun <!VIRTUAL_MEMBER_HIDDEN!>bar<!>(): B = this // Here we should have "missing override" but no ambiguity
fun test() {
foo()
@@ -563,6 +563,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
}
val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning<KtNamedDeclaration>(PositioningStrategy.OPEN_MODIFIER)
val NON_FINAL_MEMBER_IN_OBJECT by warning<KtNamedDeclaration>(PositioningStrategy.OPEN_MODIFIER)
val VIRTUAL_MEMBER_HIDDEN by error<KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME) {
parameter<FirMemberDeclaration>("declared")
parameter<FirRegularClass>("overriddenContainer")
}
}
val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") {
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
@@ -336,6 +337,7 @@ object FirErrors {
val VAR_OVERRIDDEN_BY_VAL by error2<KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning0<KtNamedDeclaration>(SourceElementPositioningStrategies.OPEN_MODIFIER)
val NON_FINAL_MEMBER_IN_OBJECT by warning0<KtNamedDeclaration>(SourceElementPositioningStrategies.OPEN_MODIFIER)
val VIRTUAL_MEMBER_HIDDEN by error2<KtNamedDeclaration, FirMemberDeclaration, FirRegularClass>(SourceElementPositioningStrategies.DECLARATION_NAME)
// Redeclarations
val MANY_COMPANION_OBJECTS by error0<KtObjectDeclaration>(SourceElementPositioningStrategies.COMPANION_OBJECT)
@@ -0,0 +1,21 @@
/*
* 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
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
interface FirOverridesBackwardCompatibilityHelper : FirSessionComponent {
fun overrideCanBeOmitted(overriddenMemberSymbols: List<FirCallableSymbol<*>>, context: CheckerContext): Boolean
class Default : FirOverridesBackwardCompatibilityHelper {
override fun overrideCanBeOmitted(overriddenMemberSymbols: List<FirCallableSymbol<*>>, context: CheckerContext): Boolean = false
}
}
val FirSession.overridesBackwardCompatibilityHelper: FirOverridesBackwardCompatibilityHelper by FirSession.sessionComponentAccessor()
@@ -49,7 +49,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
private val INLINE_ONLY_ANNOTATION_CLASS_ID = ClassId.topLevel(FqName("kotlin.internal.InlineOnly"))
internal fun FirClass<*>.unsubstitutedScope(context: CheckerContext) =
fun FirClass<*>.unsubstitutedScope(context: CheckerContext) =
this.unsubstitutedScope(context.sessionHolder.session, context.sessionHolder.scopeSession, withForcedTypeCalculator = false)
/**
@@ -7,21 +7,22 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
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.containingClass
import org.jetbrains.kotlin.fir.analysis.overridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
@@ -172,12 +173,30 @@ object FirOverrideChecker : FirClassChecker() {
firTypeScope: FirTypeScope,
context: CheckerContext,
) {
val overriddenMemberSymbols = firTypeScope.retrieveDirectOverriddenOf(member)
if (!member.isOverride) {
if (overriddenMemberSymbols.isEmpty() ||
context.session.overridesBackwardCompatibilityHelper.overrideCanBeOmitted(overriddenMemberSymbols, context)
) {
return
}
val kind = member.source?.kind
// Only report if the current member has real source or it's a member property declared inside the primary constructor.
if (kind !is FirRealSourceElementKind && kind !is FirFakeSourceElementKind.PropertyFromParameter) return
val overridden = overriddenMemberSymbols.first().originalOrSelf()
val containingClass = overridden.containingClass()?.toFirRegularClass(context.session) ?: return
reporter.reportOn(
member.source,
FirErrors.VIRTUAL_MEMBER_HIDDEN,
member,
containingClass,
context
)
return
}
val overriddenMemberSymbols = firTypeScope.retrieveDirectOverriddenOf(member)
if (overriddenMemberSymbols.isEmpty()) {
reporter.reportNothingToOverride(member, context)
return
@@ -353,6 +353,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIANCE_ON_TYPE_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_OVERRIDDEN_BY_VAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_TYPE_MISMATCH_ON_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VIRTUAL_MEMBER_HIDDEN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_GETTER_RETURN_TYPE
@@ -818,6 +819,11 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
)
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(
VIRTUAL_MEMBER_HIDDEN, "''{0}'' hides member of supertype ''{1}'' and needs ''override'' modifier", DECLARATION_NAME,
DECLARATION_NAME
)
map.put(
GENERIC_THROWABLE_SUBCLASS,
"Subclass of 'Throwable' may not have type parameters"
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.CheckersComponent
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTracker
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory
@@ -92,6 +93,7 @@ fun FirSession.registerJavaSpecificResolveComponents() {
register(FirPlatformClassMapper::class, FirJavaClassMapper(this))
register(FirSyntheticNamesProvider::class, FirJavaSyntheticNamesProvider)
register(FirJsr305StateContainer::class, FirJsr305StateContainer.Default)
register(FirOverridesBackwardCompatibilityHelper::class, FirJvmOverridesBackwardCompatibilityHelper)
}
@OptIn(SessionConfiguration::class)
@@ -0,0 +1,78 @@
/*
* 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.session
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.dispatchReceiverTypeOrNull
import org.jetbrains.kotlin.fir.originalOrSelf
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.ClassId
/**
* Helper that determines if `override` keyword can be omitted for certain overrides. In general it can be omitted if
*
* 1. the super member is annotated with `@kotlin.internal.PlatformDependent`, OR
* 2. the super member is declared in a Java class that has special Kotlin class mapping. For example, overriding members of
* `kotlin.Throwable` does not require `override` keyword.
*
* Note that, in case of multi-override, if any super member requires `override`, then the `override` keyword cannot be omitted.
*/
object FirJvmOverridesBackwardCompatibilityHelper : FirOverridesBackwardCompatibilityHelper {
private val javaOrigin = setOf(FirDeclarationOrigin.Java, FirDeclarationOrigin.Enhancement)
private val platformDependentAnnotation = ClassId.fromString("kotlin/internal/PlatformDependent")
override fun overrideCanBeOmitted(
overriddenMemberSymbols: List<FirCallableSymbol<*>>,
context: CheckerContext
): Boolean {
// Members could share the same common interface up in the hierarchy. Hence we track the visited members to avoid redundant work.
val visitedSymbols = hashSetOf<FirCallableSymbol<*>>()
return overriddenMemberSymbols.all { isPlatformSpecificSymbolThatCanBeImplicitlyOverridden(it, visitedSymbols, context) }
}
private fun isPlatformSpecificSymbolThatCanBeImplicitlyOverridden(
symbol: FirCallableSymbol<*>,
visitedSymbols: MutableSet<FirCallableSymbol<*>>,
context: CheckerContext
): Boolean {
val fir = symbol.fir as? FirCallableMemberDeclaration<*> ?: return false
if (fir.isFinal) return false
if (symbol in visitedSymbols) return true
visitedSymbols += symbol
val originalMember = fir.originalOrSelf()
if (originalMember.annotations.any { it.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.classId == platformDependentAnnotation }) {
return true
}
if (originalMember.origin !in javaOrigin) return false
val containingClassName = originalMember.containingClass()?.classId?.asSingleFqName()?.toUnsafe() ?: return false
// If the super class is mapped to a Kotlin built-in class, then we don't require `override` keyword.
if (JavaToKotlinClassMap.mapKotlinToJava(containingClassName) != null) return true
val scope =
symbol.dispatchReceiverTypeOrNull()?.toRegularClass(context.session)?.unsubstitutedScope(context) ?: return false
val overriddenSymbols = when (originalMember) {
is FirSimpleFunction -> scope.getDirectOverriddenFunctions(originalMember.symbol)
is FirProperty -> scope.getDirectOverriddenProperties(originalMember.symbol)
else -> return false
}
if (overriddenSymbols.isEmpty()) return false
return overriddenSymbols.all { isPlatformSpecificSymbolThatCanBeImplicitlyOverridden(it, visitedSymbols, context) }
}
}
@@ -71,6 +71,16 @@ inline fun <reified D : FirCallableDeclaration<*>> D.originalIfFakeOverride(): D
inline fun <reified S : FirCallableSymbol<*>> S.originalIfFakeOverride(): S? =
fir.originalIfFakeOverride()?.symbol as S?
inline fun <reified D : FirCallableDeclaration<*>> D.originalOrSelf(): D {
var result = this
while (result.isSubstitutionOrIntersectionOverride) {
result = result.originalIfFakeOverride() ?: break
}
return result
}
inline fun <reified S : FirCallableSymbol<*>> S.originalOrSelf(): S = fir.originalOrSelf().symbol as S
inline fun <reified D : FirCallableDeclaration<*>> D.unwrapFakeOverrides(): D {
var current = this
@@ -1,5 +0,0 @@
interface IA {
fun toString(): String = "IB"
override fun equals(other: Any?): Boolean
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface IA {
fun <!VIRTUAL_MEMBER_HIDDEN!>toString<!>(): String = "IB"
@@ -1,15 +0,0 @@
interface X {
fun foo(a : Int = 1)
}
interface Y {
fun foo(a : Int = 1)
}
class Z : X, Y {
fun foo(a : Int) {}
}
object ZO : X, Y {
fun foo(a : Int) {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface X {
fun foo(a : Int = 1)
}
@@ -36,8 +36,8 @@ class MyChildClass() : MyClass() {}
}
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class MyIllegalClass4<!>() : MyTrait, MyAbstractClass() {
fun foo() {}
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val pr : Unit<!>
fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>() {}
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val <!VIRTUAL_MEMBER_HIDDEN!>pr<!> : Unit<!>
override fun other() {}
override val otherPr : Int = 1
}
@@ -25,7 +25,7 @@ fun test() {
}
class E: A() {
fun foo() = A()
fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>() = A()
init {
val a: A = foo() // todo: discuss
@@ -1,18 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
abstract class Test1 : Map<String, String> {
fun containsKey(key: String): Boolean = TODO()
fun getOrDefault(key: String, defaultValue: String): String = TODO()
}
abstract class Test2 : MutableMap<String, String> {
fun replace(key: String, value: String): String? = TODO()
}
abstract class Test3 : java.util.AbstractMap<String, String>() {
fun containsKey(key: String): Boolean = TODO()
fun replace(key: String, value: String): String? = TODO()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
abstract class Test1 : Map<String, String> {
@@ -1,32 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
// Default methods from Java interfaces are NOT overridden by delegation.
// So, in the example below 'TestNoDelegationToDefaultMethods#replace' implicitly overrides a method from 'java.util.Map' (which is ok),
// but not a method from 'WithDelegation' (would be an error).
open class WithDelegation(val m: Map<String, String>) : Map<String, String> by m
class TestNoDelegationToDefaultMethods(m: Map<String, String>): WithDelegation(m) {
fun containsKey(key: String): Boolean = TODO()
fun getOrDefault(key: String, defaultValue: String): String = TODO()
fun replace(key: String, value: String): String? = TODO()
}
interface IBaseWithKotlinDeclaration : Map<String, String> {
fun replace(key: String, value: String): String?
}
abstract class WithDelegation2(val m: Map<String, String>) : Map<String, String> by m, IBaseWithKotlinDeclaration
abstract class TestNoDelegationToDefaultMethods2(m: Map<String, String>): WithDelegation2(m) {
fun containsKey(key: String): Boolean = TODO()
fun getOrDefault(key: String, defaultValue: String): String = TODO()
// VIRTUAL_MEMBER_HIDDEN: hides member declaration inherited from a Kotlin interface
fun replace(key: String, value: String): String? = TODO()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
@@ -1,15 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
interface IBaseWithKotlinDeclaration : Map<String, String> {
fun replace(key: String, value: String): String?
}
interface TestDerivedInterfaceHidingWithKotlinDeclaration : IBaseWithKotlinDeclaration {
// VIRTUAL_MEMBER_HIDDEN: hides member declaration inherited from a Kotlin interface
fun replace(key: String, value: String): String?
}
interface TestDerivedInterfaceDefaultWithKotlinDeclaration : IBaseWithKotlinDeclaration {
// VIRTUAL_MEMBER_HIDDEN: hides member declaration inherited from a Kotlin interface
fun replace(key: String, value: String): String? = TODO()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
interface IBaseWithKotlinDeclaration : Map<String, String> {
@@ -14,11 +14,11 @@ class A : java.util.ArrayList<String>() {
}
class A1 : java.util.ArrayList<String>() {
// `stream` is defined in ArrayList, so it was possible to declare it in 1.0 without an 'override' keyword
// `stream` is defined in Collection, so it was possible to declare it in 1.0 without an 'override' keyword
fun stream(): java.util.stream.Stream<String> = super.stream()
// `sort` is defined in ArrayList, so it was impossible to declare it in 1.0 without an 'override' keyword
fun sort(c: Comparator<in String>?) {
fun <!VIRTUAL_MEMBER_HIDDEN!>sort<!>(c: Comparator<in String>?) {
super.sort(c)
}
}
@@ -14,7 +14,7 @@ class A : java.util.ArrayList<String>() {
}
class A1 : java.util.ArrayList<String>() {
// `stream` is defined in ArrayList, so it was possible to declare it in 1.0 without an 'override' keyword
// `stream` is defined in Collection, so it was possible to declare it in 1.0 without an 'override' keyword
fun stream(): java.util.stream.Stream<String> = super.<!UNRESOLVED_REFERENCE!>stream<!>()
// `sort` is defined in ArrayList, so it was impossible to declare it in 1.0 without an 'override' keyword
@@ -144,6 +144,14 @@ private object FirToKtConversionCreator {
"firSymbolBuilder.classifierBuilder.buildClassLikeSymbol({0})",
KtClassLikeSymbol::class.createType()
),
FirRegularClass::class to HLFunctionCallConversion(
"firSymbolBuilder.classifierBuilder.buildClassLikeSymbol({0}) as KtNamedClassOrObjectSymbol",
KtNamedClassOrObjectSymbol::class.createType(),
importsToAdd = listOf(
"org.jetbrains.kotlin.fir.declarations.FirRegularClass",
"org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol"
)
),
FirExpression::class to HLFunctionCallConversion(
"{0}.source!!.psi as KtExpression",
KtExpression::class.createType(),
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
@@ -1589,6 +1590,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.VIRTUAL_MEMBER_HIDDEN) { firDiagnostic ->
VirtualMemberHiddenImpl(
firSymbolBuilder.buildSymbol(firDiagnostic.a as FirDeclaration),
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.b) as KtNamedClassOrObjectSymbol,
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.MANY_COMPANION_OBJECTS) { firDiagnostic ->
ManyCompanionObjectsImpl(
firDiagnostic as FirPsiDiagnostic<*>,
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableLikeSymbol
@@ -1129,6 +1130,12 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = NonFinalMemberInObject::class
}
abstract class VirtualMemberHidden : KtFirDiagnostic<KtNamedDeclaration>() {
override val diagnosticClass get() = VirtualMemberHidden::class
abstract val declared: KtSymbol
abstract val overriddenContainer: KtNamedClassOrObjectSymbol
}
abstract class ManyCompanionObjects : KtFirDiagnostic<KtObjectDeclaration>() {
override val diagnosticClass get() = ManyCompanionObjects::class
}
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableLikeSymbol
@@ -1814,6 +1815,15 @@ internal class NonFinalMemberInObjectImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class VirtualMemberHiddenImpl(
override val declared: KtSymbol,
override val overriddenContainer: KtNamedClassOrObjectSymbol,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.VirtualMemberHidden(), KtAbstractFirDiagnostic<KtNamedDeclaration> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ManyCompanionObjectsImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,