FIR checker: report VIRTUAL_MEMBER_HIDDEN
This commit is contained in:
committed by
Mikhail Glukhikh
parent
d3dfb33f89
commit
32f55a2269
@@ -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() {
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
+4
@@ -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)
|
||||
|
||||
+21
@@ -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)
|
||||
|
||||
/**
|
||||
|
||||
+23
-4
@@ -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
|
||||
|
||||
+6
@@ -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)
|
||||
|
||||
+78
@@ -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"
|
||||
|
||||
|
||||
Vendored
-15
@@ -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) {}
|
||||
}
|
||||
Vendored
+1
@@ -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
|
||||
}
|
||||
|
||||
+1
-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
|
||||
|
||||
-18
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
|
||||
|
||||
abstract class Test1 : Map<String, String> {
|
||||
|
||||
Vendored
-32
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
|
||||
|
||||
|
||||
|
||||
-15
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN
|
||||
|
||||
interface IBaseWithKotlinDeclaration : Map<String, String> {
|
||||
|
||||
+2
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+8
@@ -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(),
|
||||
|
||||
+9
@@ -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<*>,
|
||||
|
||||
+7
@@ -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
|
||||
}
|
||||
|
||||
+10
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user