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 a9a9d6929b0..39af2d399aa 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 @@ -4636,6 +4636,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirJsErrors.DELEGATION_BY_DYNAMIC) { firDiagnostic -> + DelegationByDynamicImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirSyntaxErrors.SYNTAX) { firDiagnostic -> SyntaxImpl( 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 2f5777fa712..1a93918b446 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 @@ -3225,6 +3225,10 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = JavaSamInterfaceConstructorReference::class } + abstract class DelegationByDynamic : KtFirDiagnostic() { + override val diagnosticClass get() = DelegationByDynamic::class + } + abstract class Syntax : KtFirDiagnostic() { override val diagnosticClass get() = Syntax::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 adb446af71a..314171ee09b 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 @@ -3901,6 +3901,11 @@ internal class JavaSamInterfaceConstructorReferenceImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.JavaSamInterfaceConstructorReference(), KtAbstractFirDiagnostic +internal class DelegationByDynamicImpl( + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.DelegationByDynamic(), KtAbstractFirDiagnostic + internal class SyntaxImpl( 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 417f412c9bb..bf63dd23610 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 @@ -26,4 +26,8 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") { parameter>("symbol") } } + + val DYNAMICS by object : DiagnosticGroup("Dynamics") { + val DELEGATION_BY_DYNAMIC by error() + } } 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 a2b4f6d3792..12828f7879c 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 @@ -27,6 +27,9 @@ object FirJsErrors { // Supertypes val WRONG_MULTIPLE_INHERITANCE by error1>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) + // Dynamics + val DELEGATION_BY_DYNAMIC by error0() + 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 dbdaa70cf50..c1460c95c97 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 @@ -9,6 +9,7 @@ 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.DELEGATION_BY_DYNAMIC 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 @@ -30,6 +31,7 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() { "Can''t apply multiple inheritance here, since it''s impossible to generate bridge for system function {0}", FirDiagnosticRenderers.SYMBOL ) + map.put(DELEGATION_BY_DYNAMIC, "Can't delegate to dynamic value") 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 c64260665b8..7464171a919 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 @@ -27,5 +27,6 @@ object JsDeclarationCheckers : DeclarationCheckers() { override val classCheckers: Set get() = setOf( FirJsMultipleInheritanceChecker, + FirJsDynamicDeclarationChecker, ) } diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsDynamicDeclarationChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsDynamicDeclarationChecker.kt new file mode 100644 index 00000000000..de3385fd77f --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsDynamicDeclarationChecker.kt @@ -0,0 +1,35 @@ +/* + * 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.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.diagnostics.js.FirJsErrors +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.delegateFieldsMap +import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.types.ConeDynamicType +import org.jetbrains.kotlin.fir.types.coneType + +object FirJsDynamicDeclarationChecker : FirClassChecker() { + override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { + val delegatedFields = declaration.delegateFieldsMap ?: return + + for ((_, delegate) in delegatedFields) { + @OptIn(SymbolInternals::class) + // Accessing fir here is ok, because it still + // belongs to the current `declaration: FirClass`, + // and it's a shape it couldn't have been accessed directly + val initializer = delegate.fir.initializer ?: continue + + if (initializer.typeRef.coneType is ConeDynamicType) { + reporter.reportOn(initializer.source, FirJsErrors.DELEGATION_BY_DYNAMIC, context) + } + } + } +} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/classDelegateBy.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/classDelegateBy.fir.kt deleted file mode 100644 index edae7a13682..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/classDelegateBy.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -val x: dynamic = 23 - -interface I { - fun foo(): String -} - -class C : I by x - -object O : I by x - -fun box(): String { - return object : I by x {}.foo() -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/classDelegateBy.kt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/classDelegateBy.kt index 20c9e145b0d..743d55e80eb 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/classDelegateBy.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/classDelegateBy.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL val x: dynamic = 23 interface I {