From eed2fada1f28879d9e79d455f82f0ad8e20b671b Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Tue, 3 Jan 2023 14:30:40 +0200 Subject: [PATCH] [FIR JS] Support WRONG_MULTIPLE_INHERITANCE --- .../diagnostics/KtFirDataClassConverters.kt | 7 ++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 5 ++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 6 ++ .../diagnostics/FirJsDiagnosticsList.kt | 7 ++ .../analysis/diagnostics/js/FirJsErrors.kt | 4 ++ .../js/FirJsErrorsDefaultMessages.kt | 7 ++ .../js/checkers/JsDeclarationCheckers.kt | 14 ++-- .../FirJsMultipleInheritanceChecker.kt | 64 +++++++++++++++++++ .../org/jetbrains/kotlin/fir/FirSession.kt | 3 + .../types/impl/FirImplicitBuiltinTypeRef.kt | 10 +++ .../wrongMultipleInheritance.kt | 1 + .../kotlin/builtins/StandardNames.kt | 2 + .../jetbrains/kotlin/name/StandardClassIds.kt | 1 + 13 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsMultipleInheritanceChecker.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index d7da385b1db..a9a9d6929b0 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -598,6 +598,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirJsErrors.WRONG_MULTIPLE_INHERITANCE) { firDiagnostic -> + WrongMultipleInheritanceImpl( + firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.CONSTRUCTOR_IN_OBJECT) { firDiagnostic -> ConstructorInObjectImpl( firDiagnostic as KtPsiDiagnostic, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 1d5bbb166a5..2f5777fa712 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -447,6 +447,11 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val candidates: List } + abstract class WrongMultipleInheritance : KtFirDiagnostic() { + override val diagnosticClass get() = WrongMultipleInheritance::class + abstract val symbol: KtCallableSymbol + } + abstract class ConstructorInObject : KtFirDiagnostic() { override val diagnosticClass get() = ConstructorInObject::class } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index d62c6097550..adb446af71a 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -527,6 +527,12 @@ internal class AmbiguousSuperImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.AmbiguousSuper(), KtAbstractFirDiagnostic +internal class WrongMultipleInheritanceImpl( + override val symbol: KtCallableSymbol, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.WrongMultipleInheritance(), KtAbstractFirDiagnostic + internal class ConstructorInObjectImpl( override val firDiagnostic: KtPsiDiagnostic, override val token: KtLifetimeToken, diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJsDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJsDiagnosticsList.kt index 038cd23422f..417f412c9bb 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJsDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirJsDiagnosticsList.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.checkers.generator.diagnostics import org.jetbrains.kotlin.fir.PrivateForInline import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.PositioningStrategy +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.psi.KtElement @Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused") @@ -19,4 +20,10 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") { val JS_MODULE_PROHIBITED_ON_NON_NATIVE by error(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) val NESTED_JS_MODULE_PROHIBITED by error(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) } + + val SUPERTYPES by object : DiagnosticGroup("Supertypes") { + val WRONG_MULTIPLE_INHERITANCE by error(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) { + parameter>("symbol") + } + } } diff --git a/compiler/fir/checkers/checkers.js/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/js/FirJsErrors.kt b/compiler/fir/checkers/checkers.js/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/js/FirJsErrors.kt index cd0cc46dc38..a2b4f6d3792 100644 --- a/compiler/fir/checkers/checkers.js/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/js/FirJsErrors.kt +++ b/compiler/fir/checkers/checkers.js/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/js/FirJsErrors.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.diagnostics.* import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory import org.jetbrains.kotlin.fir.analysis.diagnostics.* +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.psi.KtElement /* @@ -23,6 +24,9 @@ object FirJsErrors { val JS_MODULE_PROHIBITED_ON_NON_NATIVE by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) val NESTED_JS_MODULE_PROHIBITED by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) + // Supertypes + val WRONG_MULTIPLE_INHERITANCE by error1>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) + init { RootDiagnosticRendererFactory.registerFactory(FirJsErrorsDefaultMessages) } diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/diagnostics/js/FirJsErrorsDefaultMessages.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/diagnostics/js/FirJsErrorsDefaultMessages.kt index c5778fb309d..dbdaa70cf50 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/diagnostics/js/FirJsErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/diagnostics/js/FirJsErrorsDefaultMessages.kt @@ -7,11 +7,13 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.js import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers import org.jetbrains.kotlin.fir.analysis.diagnostics.checkMissingMessages import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_MODULE_PROHIBITED_ON_NON_NATIVE import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_MODULE_PROHIBITED_ON_VAR import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NESTED_JS_MODULE_PROHIBITED import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_JS_QUALIFIER +import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_MULTIPLE_INHERITANCE @Suppress("unused") object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() { @@ -23,6 +25,11 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() { NESTED_JS_MODULE_PROHIBITED, "@JsModule and @JsNonModule can't appear on here since the file is already marked by either @JsModule or @JsNonModule" ) + map.put( + WRONG_MULTIPLE_INHERITANCE, + "Can''t apply multiple inheritance here, since it''s impossible to generate bridge for system function {0}", + FirDiagnosticRenderers.SYMBOL + ) map.checkMissingMessages(FirJsErrors) } diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt index 66acec68a38..c64260665b8 100644 --- a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/JsDeclarationCheckers.kt @@ -5,13 +5,8 @@ package org.jetbrains.kotlin.fir.analysis.js.checkers -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirFunctionChecker -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirPropertyChecker -import org.jetbrains.kotlin.fir.analysis.js.checkers.declaration.FirJsInlineDeclarationChecker -import org.jetbrains.kotlin.fir.analysis.js.checkers.declaration.FirJsInlinePropertyChecker -import org.jetbrains.kotlin.fir.analysis.js.checkers.declaration.FirJsModuleChecker +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.* +import org.jetbrains.kotlin.fir.analysis.js.checkers.declaration.* object JsDeclarationCheckers : DeclarationCheckers() { override val functionCheckers: Set @@ -28,4 +23,9 @@ object JsDeclarationCheckers : DeclarationCheckers() { get() = setOf( FirJsModuleChecker, ) + + override val classCheckers: Set + get() = setOf( + FirJsMultipleInheritanceChecker, + ) } diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsMultipleInheritanceChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsMultipleInheritanceChecker.kt new file mode 100644 index 00000000000..22be469fabf --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsMultipleInheritanceChecker.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2023 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.js.checkers.declaration + +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker +import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions +import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope +import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.resolve.defaultType +import org.jetbrains.kotlin.fir.scopes.getFunctions +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.classId +import org.jetbrains.kotlin.fir.types.isSubtypeOf +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.util.OperatorNameConventions + +object FirJsMultipleInheritanceChecker : FirClassChecker() { + override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { + declaration.checkFunctionIfSubtypeOf( + functionToCheck = OperatorNameConventions.GET, + supertype = context.session.builtinTypes.charSequenceType.type, + context, reporter, + ) + + declaration.checkFunctionIfSubtypeOf( + functionToCheck = StandardNames.NEXT_CHAR, + supertype = context.session.builtinTypes.charIteratorType.type, + context, reporter, + ) + } + + private fun FirClass.checkFunctionIfSubtypeOf( + functionToCheck: Name, + supertype: ConeKotlinType, + context: CheckerContext, + reporter: DiagnosticReporter, + ) { + if (!defaultType().isSubtypeOf(supertype, context.session)) { + return + } + + val scope = unsubstitutedScope(context) + val overridesWithSameName = scope.getFunctions(functionToCheck) + + for (function in overridesWithSameName) { + val overridden = function.overriddenFunctions(symbol, context) + + if ( + overridden.size > 1 && + overridden.any { it.callableId.classId == supertype.classId } + ) { + reporter.reportOn(source, FirJsErrors.WRONG_MULTIPLE_INHERITANCE, function, context) + } + } + } +} \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt index a4fb13a5d08..d0ef4c8bf5e 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt @@ -74,4 +74,7 @@ class BuiltinTypes { val charType: FirImplicitBuiltinTypeRef = FirImplicitCharTypeRef(null) val stringType: FirImplicitBuiltinTypeRef = FirImplicitStringTypeRef(null) val throwableType: FirImplicitThrowableTypeRef = FirImplicitThrowableTypeRef(null) + + val charSequenceType: FirImplicitCharSequenceTypeRef = FirImplicitCharSequenceTypeRef(null) + val charIteratorType: FirImplicitCharIteratorTypeRef = FirImplicitCharIteratorTypeRef(null) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/impl/FirImplicitBuiltinTypeRef.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/impl/FirImplicitBuiltinTypeRef.kt index bbb5fb9dc63..6f891210291 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/impl/FirImplicitBuiltinTypeRef.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/impl/FirImplicitBuiltinTypeRef.kt @@ -128,6 +128,14 @@ class FirImplicitThrowableTypeRef( source: KtSourceElement? ) : FirImplicitBuiltinTypeRef(source, StandardClassIds.Throwable) +class FirImplicitCharSequenceTypeRef( + source: KtSourceElement? +) : FirImplicitBuiltinTypeRef(source, StandardClassIds.CharSequence) + +class FirImplicitCharIteratorTypeRef( + source: KtSourceElement? +) : FirImplicitBuiltinTypeRef(source, StandardClassIds.CharIterator) + class FirImplicitKPropertyTypeRef( source: KtSourceElement?, typeArgument: ConeTypeProjection @@ -199,6 +207,8 @@ fun FirImplicitBuiltinTypeRef.withFakeSource(kind: KtFakeSourceElementKind): Fir is FirImplicitCharTypeRef -> FirImplicitCharTypeRef(newSource) is FirImplicitStringTypeRef -> FirImplicitStringTypeRef(newSource) is FirImplicitThrowableTypeRef -> FirImplicitThrowableTypeRef(newSource) + is FirImplicitCharSequenceTypeRef -> FirImplicitCharSequenceTypeRef(newSource) + is FirImplicitCharIteratorTypeRef -> FirImplicitCharIteratorTypeRef(newSource) is FirImplicitKPropertyTypeRef -> FirImplicitKPropertyTypeRef( newSource, typeArgument = type.typeArguments[0] diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/wrongMultipleInheritance.kt b/compiler/testData/diagnostics/testsWithJsStdLib/wrongMultipleInheritance.kt index 5f79668bc00..f7672feb001 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/wrongMultipleInheritance.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/wrongMultipleInheritance.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER open class A { diff --git a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt index c489fdd06f2..bc52c5a83d1 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt @@ -34,6 +34,8 @@ object StandardNames { @JvmField val CHAR_CODE = Name.identifier("code") + @JvmField val NEXT_CHAR = Name.identifier("nextChar") + @JvmField val CONTEXT_FUNCTION_TYPE_PARAMETER_COUNT_NAME = Name.identifier("count") @JvmField val DYNAMIC_FQ_NAME = FqName("") diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt index 67d0b4df278..c3497c4ff38 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt @@ -116,6 +116,7 @@ object StandardClassIds { val Set = "Set".collectionsId() val Map = "Map".collectionsId() val MutableIterator = "MutableIterator".collectionsId() + val CharIterator = "CharIterator".collectionsId() val MutableIterable = "MutableIterable".collectionsId() val MutableCollection = "MutableCollection".collectionsId()