From 478c1a6d5051c4a2d7c4548b84d26992837709c9 Mon Sep 17 00:00:00 2001 From: Stanislav Ruban Date: Mon, 11 Mar 2024 04:04:58 +0200 Subject: [PATCH] [FIR][checkers][JS] Move reporting of FirJsErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE to FirJsInheritanceClassChecker #KT-66474 Fixed --- .../declaration/FirJsExternalChecker.kt | 20 ---------------- .../FirJsInheritanceClassChecker.kt | 24 ++++++++++++++----- ...ternalTypeExtendsActualExternalType.fir.kt | 2 +- ...xternalTypeExtendsActualExternalType.ll.kt | 13 ++++++++++ 4 files changed, 32 insertions(+), 27 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multiplatform/JsExternalTypeExtendsActualExternalType.ll.kt diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsExternalChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsExternalChecker.kt index 1e2570bbd5c..9a3fe4f424c 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsExternalChecker.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsExternalChecker.kt @@ -41,20 +41,6 @@ object FirJsExternalChecker : FirWebCommonExternalChecker(allowCompanionInInterf } override fun additionalCheck(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { - if (declaration is FirClass && declaration.classKind != ClassKind.ANNOTATION_CLASS) { - val superClasses = declaration.superInterfaces(context.session).toMutableList() - declaration.superClassNotAny(context.session)?.let { - superClasses.add(it) - } - if (declaration.classKind == ClassKind.ENUM_CLASS || declaration.classKind == ClassKind.ENUM_ENTRY) { - superClasses.removeAll { it.classId?.asSingleFqName()?.toUnsafe() == StandardNames.FqNames._enum } - } - val superDeclarations = superClasses.mapNotNull { it.toSymbol(context.session) } - if (superDeclarations.any { !it.isNativeObject(context) && it.classId.asSingleFqName() != StandardNames.FqNames.throwable }) { - reporter.reportOn(declaration.source, FirJsErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE, context) - } - } - if (declaration is FirFunction && declaration.isInline) { reporter.reportOn(declaration.source, FirWebCommonErrors.INLINE_EXTERNAL_DECLARATION, context) } @@ -136,10 +122,6 @@ object FirJsExternalChecker : FirWebCommonExternalChecker(allowCompanionInInterf else -> returnTypeRef.coneType.typeArguments.firstOrNull()?.type } - private fun FirClass.superInterfaces(session: FirSession) = superConeTypes - .filterNot { it.isAny || it.isNullableAny } - .filter { it.toSymbol(session)?.classKind == ClassKind.INTERFACE } - private fun FirDeclaration.checkEnumEntry(context: CheckerContext, reporter: DiagnosticReporter) { if (this !is FirEnumEntry) return initializer?.let { @@ -147,5 +129,3 @@ object FirJsExternalChecker : FirWebCommonExternalChecker(allowCompanionInInterf } } } - - diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInheritanceClassChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInheritanceClassChecker.kt index fb897410e7d..0ae1bdbd7f4 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInheritanceClassChecker.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsInheritanceClassChecker.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.analysis.js.checkers.declaration import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.FirSession @@ -15,17 +16,15 @@ import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors -import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal import org.jetbrains.kotlin.fir.analysis.js.checkers.isOverridingExternalWithOptionalParams import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes import org.jetbrains.kotlin.fir.scopes.collectAllFunctions import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.isSuspendOrKSuspendFunctionType -import org.jetbrains.kotlin.fir.types.typeContext +import org.jetbrains.kotlin.fir.types.* sealed class FirJsInheritanceClassChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) { object Regular : FirJsInheritanceClassChecker(MppCheckerKind.Platform) { @@ -43,7 +42,20 @@ sealed class FirJsInheritanceClassChecker(mppKind: MppCheckerKind) : FirClassChe } override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { - if (!declaration.symbol.isEffectivelyExternal(context)) { + val session = context.session + val isEffectivelyExternal = declaration.symbol.isEffectivelyExternal(session) + + if (isEffectivelyExternal && declaration.classKind != ClassKind.ANNOTATION_CLASS) { + val superTypes = declaration.superConeTypes + .filterNot { it.isAnyOrNullableAny || it.isThrowableOrNullableThrowable || it.isEnum } + .mapNotNull { it.toSymbol(session) } + + if (superTypes.any { !it.isEffectivelyExternal(session) }) { + reporter.reportOn(declaration.source, FirJsErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE, context) + } + } + + if (!isEffectivelyExternal) { val fakeOverriddenMethod = declaration.findFakeMethodOverridingExternalWithOptionalParams(context) if (fakeOverriddenMethod != null) { @@ -57,7 +69,7 @@ sealed class FirJsInheritanceClassChecker(mppKind: MppCheckerKind) : FirClassChe if ( !context.languageVersionSettings.supportsFeature(LanguageFeature.JsAllowImplementingFunctionInterface) && declaration.superConeTypes.any { - it.isBuiltinFunctionalTypeOrSubtype(context.session) && !it.isSuspendFunctionTypeOrSubtype(context.session) + it.isBuiltinFunctionalTypeOrSubtype(session) && !it.isSuspendFunctionTypeOrSubtype(session) } ) { reporter.reportOn(declaration.source, FirJsErrors.IMPLEMENTING_FUNCTION_INTERFACE, context) diff --git a/compiler/testData/diagnostics/tests/multiplatform/JsExternalTypeExtendsActualExternalType.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/JsExternalTypeExtendsActualExternalType.fir.kt index 7ac952ccdfd..88c709e624d 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/JsExternalTypeExtendsActualExternalType.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/JsExternalTypeExtendsActualExternalType.fir.kt @@ -4,7 +4,7 @@ expect interface ExternalInterface -external class ExternalClass: ExternalInterface +external class ExternalClass: ExternalInterface // MODULE: js()()(commonjs) // TARGET_PLATFORM: JS diff --git a/compiler/testData/diagnostics/tests/multiplatform/JsExternalTypeExtendsActualExternalType.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/JsExternalTypeExtendsActualExternalType.ll.kt new file mode 100644 index 00000000000..7ac952ccdfd --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/JsExternalTypeExtendsActualExternalType.ll.kt @@ -0,0 +1,13 @@ +// MODULE: commonjs +// TARGET_PLATFORM: JS +// FILE: commonjs.kt + +expect interface ExternalInterface + +external class ExternalClass: ExternalInterface + +// MODULE: js()()(commonjs) +// TARGET_PLATFORM: JS +// FILE: js.kt + +actual external interface ExternalInterface