From 32f55a22692de4a8308b1b87d6b79bf9feef026b Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Mon, 24 May 2021 13:29:32 -0700 Subject: [PATCH] FIR checker: report VIRTUAL_MEMBER_HIDDEN --- .../testData/resolve/overrides/simple.kt | 2 +- .../properties/kotlinOverridesJavaComplex.kt | 2 +- .../resolveWithStdlib/j+k/OverrideWithJava.kt | 2 +- .../diagnostics/FirDiagnosticsList.kt | 4 + .../fir/analysis/diagnostics/FirErrors.kt | 2 + ...FirOverridesBackwardCompatibilityHelper.kt | 21 +++++ .../fir/analysis/checkers/FirHelpers.kt | 2 +- .../declaration/FirOverrideChecker.kt | 27 ++++++- .../diagnostics/FirDefaultErrorMessages.kt | 6 ++ .../fir/session/ComponentsContainers.kt | 2 + ...JvmOverridesBackwardCompatibilityHelper.kt | 78 +++++++++++++++++++ .../org/jetbrains/kotlin/fir/ClassMembers.kt | 10 +++ .../java8Overrides/hidingMethodOfAny.fir.kt | 5 -- .../tests/java8Overrides/hidingMethodOfAny.kt | 1 + ...ultParametersInSupertypesNoOverride.fir.kt | 15 ---- ...DefaultParametersInSupertypesNoOverride.kt | 1 + .../tests/override/NonGenerics.fir.kt | 4 +- .../scopes/inheritance/methodsPriority.fir.kt | 2 +- .../backwardCompatibility/basic.fir.kt | 18 ----- .../backwardCompatibility/basic.kt | 1 + .../backwardCompatibility/delegation.fir.kt | 32 -------- .../backwardCompatibility/delegation.kt | 1 + .../derivedInterfacesWithKotlinFun.fir.kt | 15 ---- .../derivedInterfacesWithKotlinFun.kt | 1 + .../unsupportedFeature.fir.kt | 4 +- .../targetedBuiltIns/unsupportedFeature.kt | 2 +- .../fir/generator/HLDiagnosticConverter.kt | 8 ++ .../diagnostics/KtFirDataClassConverters.kt | 9 +++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 7 ++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 10 +++ 30 files changed, 195 insertions(+), 99 deletions(-) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirOverridesBackwardCompatibilityHelper.kt create mode 100644 compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirJvmOverridesBackwardCompatibilityHelper.kt delete mode 100644 compiler/testData/diagnostics/tests/java8Overrides/hidingMethodOfAny.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/basic.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/delegation.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/derivedInterfacesWithKotlinFun.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/overrides/simple.kt b/compiler/fir/analysis-tests/testData/resolve/overrides/simple.kt index f87bf8fb820..59cebb11ff3 100644 --- a/compiler/fir/analysis-tests/testData/resolve/overrides/simple.kt +++ b/compiler/fir/analysis-tests/testData/resolve/overrides/simple.kt @@ -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 bar(): B = this // Missing 'override' override fun buz(p: B): B = this //No override as B not :> A fun test() { diff --git a/compiler/fir/analysis-tests/testData/resolve/properties/kotlinOverridesJavaComplex.kt b/compiler/fir/analysis-tests/testData/resolve/properties/kotlinOverridesJavaComplex.kt index faf0d3f2565..7f5d6fa954c 100644 --- a/compiler/fir/analysis-tests/testData/resolve/properties/kotlinOverridesJavaComplex.kt +++ b/compiler/fir/analysis-tests/testData/resolve/properties/kotlinOverridesJavaComplex.kt @@ -44,7 +44,7 @@ public class LightClassWrapper : Light(), } public abstract class Light : Field, TypeParametersOwner { - fun getTypeParameters() = listOf() + fun getTypeParameters() = listOf() } public interface Field : Named diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/OverrideWithJava.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/OverrideWithJava.kt index 9dc95ae90d9..d710ab42b38 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/OverrideWithJava.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/j+k/OverrideWithJava.kt @@ -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 bar(): B = this // Here we should have "missing override" but no ambiguity fun test() { foo() diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 9981bb88264..a4d88acbc88 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -563,6 +563,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { } val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning(PositioningStrategy.OPEN_MODIFIER) val NON_FINAL_MEMBER_IN_OBJECT by warning(PositioningStrategy.OPEN_MODIFIER) + val VIRTUAL_MEMBER_HIDDEN by error(PositioningStrategy.DECLARATION_NAME) { + parameter("declared") + parameter("overriddenContainer") + } } val REDECLARATIONS by object : DiagnosticGroup("Redeclarations") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index dec17032ce8..60d43095529 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -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(SourceElementPositioningStrategies.VAL_OR_VAR_NODE) val NON_FINAL_MEMBER_IN_FINAL_CLASS by warning0(SourceElementPositioningStrategies.OPEN_MODIFIER) val NON_FINAL_MEMBER_IN_OBJECT by warning0(SourceElementPositioningStrategies.OPEN_MODIFIER) + val VIRTUAL_MEMBER_HIDDEN by error2(SourceElementPositioningStrategies.DECLARATION_NAME) // Redeclarations val MANY_COMPANION_OBJECTS by error0(SourceElementPositioningStrategies.COMPANION_OBJECT) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirOverridesBackwardCompatibilityHelper.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirOverridesBackwardCompatibilityHelper.kt new file mode 100644 index 00000000000..5d3faa1c94d --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirOverridesBackwardCompatibilityHelper.kt @@ -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>, context: CheckerContext): Boolean + + class Default : FirOverridesBackwardCompatibilityHelper { + override fun overrideCanBeOmitted(overriddenMemberSymbols: List>, context: CheckerContext): Boolean = false + } +} + +val FirSession.overridesBackwardCompatibilityHelper: FirOverridesBackwardCompatibilityHelper by FirSession.sessionComponentAccessor() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 5a7dae1fab8..07b343e54cd 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -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) /** diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt index f5c1eb8db36..10e557169f5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt @@ -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 diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 381e1ae85d1..df8b5bb3512 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -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" diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt index 3c58b27f8c3..ed99ffa5bcf 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt @@ -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) diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirJvmOverridesBackwardCompatibilityHelper.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirJvmOverridesBackwardCompatibilityHelper.kt new file mode 100644 index 00000000000..4edbe39e04a --- /dev/null +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirJvmOverridesBackwardCompatibilityHelper.kt @@ -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>, + 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>() + return overriddenMemberSymbols.all { isPlatformSpecificSymbolThatCanBeImplicitlyOverridden(it, visitedSymbols, context) } + } + + private fun isPlatformSpecificSymbolThatCanBeImplicitlyOverridden( + symbol: FirCallableSymbol<*>, + visitedSymbols: MutableSet>, + 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()?.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) } + } +} \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt index 60e1d4705f2..976b63845e9 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/ClassMembers.kt @@ -71,6 +71,16 @@ inline fun > D.originalIfFakeOverride(): D inline fun > S.originalIfFakeOverride(): S? = fir.originalIfFakeOverride()?.symbol as S? +inline fun > D.originalOrSelf(): D { + var result = this + while (result.isSubstitutionOrIntersectionOverride) { + result = result.originalIfFakeOverride() ?: break + } + return result +} + +inline fun > S.originalOrSelf(): S = fir.originalOrSelf().symbol as S + inline fun > D.unwrapFakeOverrides(): D { var current = this diff --git a/compiler/testData/diagnostics/tests/java8Overrides/hidingMethodOfAny.fir.kt b/compiler/testData/diagnostics/tests/java8Overrides/hidingMethodOfAny.fir.kt deleted file mode 100644 index ef0f562557e..00000000000 --- a/compiler/testData/diagnostics/tests/java8Overrides/hidingMethodOfAny.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -interface IA { - fun toString(): String = "IB" - - override fun equals(other: Any?): Boolean -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/java8Overrides/hidingMethodOfAny.kt b/compiler/testData/diagnostics/tests/java8Overrides/hidingMethodOfAny.kt index 0704b2693f3..7fdce4c42c5 100644 --- a/compiler/testData/diagnostics/tests/java8Overrides/hidingMethodOfAny.kt +++ b/compiler/testData/diagnostics/tests/java8Overrides/hidingMethodOfAny.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface IA { fun toString(): String = "IB" diff --git a/compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.fir.kt b/compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.fir.kt deleted file mode 100644 index e00f26b093a..00000000000 --- a/compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.fir.kt +++ /dev/null @@ -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) {} -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.kt b/compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.kt index f7160d06304..fd03fbcc64d 100644 --- a/compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.kt +++ b/compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface X { fun foo(a : Int = 1) } diff --git a/compiler/testData/diagnostics/tests/override/NonGenerics.fir.kt b/compiler/testData/diagnostics/tests/override/NonGenerics.fir.kt index 1f259df7adf..7531f35ea21 100644 --- a/compiler/testData/diagnostics/tests/override/NonGenerics.fir.kt +++ b/compiler/testData/diagnostics/tests/override/NonGenerics.fir.kt @@ -36,8 +36,8 @@ class MyChildClass() : MyClass() {} } class MyIllegalClass4() : MyTrait, MyAbstractClass() { - fun foo() {} - val pr : Unit + fun foo() {} + val pr : Unit override fun other() {} override val otherPr : Int = 1 } diff --git a/compiler/testData/diagnostics/tests/scopes/inheritance/methodsPriority.fir.kt b/compiler/testData/diagnostics/tests/scopes/inheritance/methodsPriority.fir.kt index a947edfa09e..94f927ff1c2 100644 --- a/compiler/testData/diagnostics/tests/scopes/inheritance/methodsPriority.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/inheritance/methodsPriority.fir.kt @@ -25,7 +25,7 @@ fun test() { } class E: A() { - fun foo() = A() + fun foo() = A() init { val a: A = foo() // todo: discuss diff --git a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/basic.fir.kt b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/basic.fir.kt deleted file mode 100644 index b20feb73784..00000000000 --- a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/basic.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN - -abstract class Test1 : Map { - fun containsKey(key: String): Boolean = TODO() - - fun getOrDefault(key: String, defaultValue: String): String = TODO() -} - -abstract class Test2 : MutableMap { - fun replace(key: String, value: String): String? = TODO() -} - -abstract class Test3 : java.util.AbstractMap() { - fun containsKey(key: String): Boolean = TODO() - - fun replace(key: String, value: String): String? = TODO() -} - diff --git a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/basic.kt b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/basic.kt index 9dab6a362b5..4be57e8bd55 100644 --- a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/basic.kt +++ b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/basic.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN abstract class Test1 : Map { diff --git a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/delegation.fir.kt b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/delegation.fir.kt deleted file mode 100644 index affebd4e03f..00000000000 --- a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/delegation.fir.kt +++ /dev/null @@ -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) : Map by m - -class TestNoDelegationToDefaultMethods(m: Map): 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 { - fun replace(key: String, value: String): String? -} - -abstract class WithDelegation2(val m: Map) : Map by m, IBaseWithKotlinDeclaration - -abstract class TestNoDelegationToDefaultMethods2(m: Map): 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() -} diff --git a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/delegation.kt b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/delegation.kt index 83381fd92e4..410feb91d44 100644 --- a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/delegation.kt +++ b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/delegation.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN diff --git a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/derivedInterfacesWithKotlinFun.fir.kt b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/derivedInterfacesWithKotlinFun.fir.kt deleted file mode 100644 index bc6ac7dde3e..00000000000 --- a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/derivedInterfacesWithKotlinFun.fir.kt +++ /dev/null @@ -1,15 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN - -interface IBaseWithKotlinDeclaration : Map { - 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() -} diff --git a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/derivedInterfacesWithKotlinFun.kt b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/derivedInterfacesWithKotlinFun.kt index 7da1c1f8486..7ebf2997f3d 100644 --- a/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/derivedInterfacesWithKotlinFun.kt +++ b/compiler/testData/diagnostics/tests/targetedBuiltIns/backwardCompatibility/derivedInterfacesWithKotlinFun.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER -PLATFORM_CLASS_MAPPED_TO_KOTLIN interface IBaseWithKotlinDeclaration : Map { diff --git a/compiler/testData/diagnostics/testsWithStdLib/targetedBuiltIns/unsupportedFeature.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/targetedBuiltIns/unsupportedFeature.fir.kt index 7f2b40b9908..21eb6458023 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/targetedBuiltIns/unsupportedFeature.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/targetedBuiltIns/unsupportedFeature.fir.kt @@ -14,11 +14,11 @@ class A : java.util.ArrayList() { } class A1 : java.util.ArrayList() { - // `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 = 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?) { + fun sort(c: Comparator?) { super.sort(c) } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/targetedBuiltIns/unsupportedFeature.kt b/compiler/testData/diagnostics/testsWithStdLib/targetedBuiltIns/unsupportedFeature.kt index 399a8b4a2d4..846d472474f 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/targetedBuiltIns/unsupportedFeature.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/targetedBuiltIns/unsupportedFeature.kt @@ -14,7 +14,7 @@ class A : java.util.ArrayList() { } class A1 : java.util.ArrayList() { - // `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 = super.stream() // `sort` is defined in ArrayList, so it was impossible to declare it in 1.0 without an 'override' keyword diff --git a/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt b/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt index a63213e3188..3a13e461c7d 100644 --- a/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt +++ b/idea/idea-frontend-fir/idea-frontend-fir-generator/src/org/jetbrains/kotlin/idea/frontend/api/fir/generator/HLDiagnosticConverter.kt @@ -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(), diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 136cff54041..2cdcc4be4f1 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -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<*>, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 26e33bf598c..1bdd67c62a7 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -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 : KtDiagnosticWithPsi { override val diagnosticClass get() = NonFinalMemberInObject::class } + abstract class VirtualMemberHidden : KtFirDiagnostic() { + override val diagnosticClass get() = VirtualMemberHidden::class + abstract val declared: KtSymbol + abstract val overriddenContainer: KtNamedClassOrObjectSymbol + } + abstract class ManyCompanionObjects : KtFirDiagnostic() { override val diagnosticClass get() = ManyCompanionObjects::class } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index c7aab0056e5..fbe6826d34c 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -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 { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class ManyCompanionObjectsImpl( firDiagnostic: FirPsiDiagnostic<*>, override val token: ValidityToken,