diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsPlatformDiagnosticSuppressor.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsPlatformDiagnosticSuppressor.kt new file mode 100644 index 00000000000..b2d60325893 --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/FirJsPlatformDiagnosticSuppressor.kt @@ -0,0 +1,22 @@ +/* + * 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 + +import org.jetbrains.kotlin.fir.analysis.checkers.FirPlatformDiagnosticSuppressor +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.hasAnnotationOrInsideAnnotatedClass +import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.name.JsStandardClassIds + +private fun FirDeclaration.isLexicallyInsideJsNative(context: CheckerContext): Boolean { + return JsStandardClassIds.Annotations.nativeAnnotations.any { hasAnnotationOrInsideAnnotatedClass(it, context.session) } +} + +object FirJsPlatformDiagnosticSuppressor : FirPlatformDiagnosticSuppressor { + override fun shouldReportNoBody(declaration: FirCallableDeclaration, context: CheckerContext) = + !declaration.isLexicallyInsideJsNative(context) +} 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 b4b47930b93..eeff8997e78 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 @@ -37,6 +37,7 @@ object JsDeclarationCheckers : DeclarationCheckers() { override val simpleFunctionCheckers: Set get() = setOf( + FirJsTopLevelFunctionsChecker, FirJsNativeInvokeChecker, FirJsNativeGetterChecker, FirJsNativeSetterChecker, diff --git a/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsTopLevelFunctionsChecker.kt b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsTopLevelFunctionsChecker.kt new file mode 100644 index 00000000000..3337e04fd30 --- /dev/null +++ b/compiler/fir/checkers/checkers.js/src/org/jetbrains/kotlin/fir/analysis/js/checkers/declaration/FirJsTopLevelFunctionsChecker.kt @@ -0,0 +1,13 @@ +/* + * 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.fir.analysis.checkers.declaration.FirTopLevelFunctionsChecker +import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsPlatformDiagnosticSuppressor + +object FirJsTopLevelFunctionsChecker : FirTopLevelFunctionsChecker() { + override val suppressor = FirJsPlatformDiagnosticSuppressor +} diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt index e0adbd24ca9..97599ae95ed 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/JvmDeclarationCheckers.kt @@ -52,4 +52,9 @@ object JvmDeclarationCheckers : DeclarationCheckers() { get() = setOf( FirUpperBoundsChecker, ) + + override val simpleFunctionCheckers: Set + get() = setOf( + FirJvmTopLevelFunctionsChecker, + ) } diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmTopLevelFunctionsChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmTopLevelFunctionsChecker.kt new file mode 100644 index 00000000000..ecfd6175378 --- /dev/null +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/declaration/FirJvmTopLevelFunctionsChecker.kt @@ -0,0 +1,13 @@ +/* + * 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.jvm.checkers.declaration + +import org.jetbrains.kotlin.fir.analysis.checkers.FirPlatformDiagnosticSuppressor +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirTopLevelFunctionsChecker + +object FirJvmTopLevelFunctionsChecker : FirTopLevelFunctionsChecker() { + override val suppressor = FirPlatformDiagnosticSuppressor.Default +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt index 627f8acb56b..c0ce80ffc35 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt @@ -54,7 +54,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() { FirFunctionTypeParametersSyntaxChecker, FirOperatorModifierChecker, FirTailrecFunctionChecker, - FirTopLevelFunctionsChecker, FirMemberFunctionsChecker, FirDataObjectContentChecker, ) 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 ebbfb14241e..defc5028325 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 @@ -730,3 +730,6 @@ fun FirBasedSymbol<*>.hasAnnotationOrInsideAnnotatedClass(classId: ClassId, sess val container = getContainingClassSymbol(session) ?: return false return container.hasAnnotationOrInsideAnnotatedClass(classId, session) } + +fun FirDeclaration.hasAnnotationOrInsideAnnotatedClass(classId: ClassId, session: FirSession) = + symbol.hasAnnotationOrInsideAnnotatedClass(classId, session) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirPlatformDiagnosticSuppressor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirPlatformDiagnosticSuppressor.kt new file mode 100644 index 00000000000..702ccdc18de --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirPlatformDiagnosticSuppressor.kt @@ -0,0 +1,17 @@ +/* + * 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.checkers + +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration + +interface FirPlatformDiagnosticSuppressor { + fun shouldReportNoBody(declaration: FirCallableDeclaration, context: CheckerContext): Boolean + + object Default : FirPlatformDiagnosticSuppressor { + override fun shouldReportNoBody(declaration: FirCallableDeclaration, context: CheckerContext): Boolean = true + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelFunctionsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelFunctionsChecker.kt index 2fa4b59fa52..2fe94567969 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelFunctionsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelFunctionsChecker.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.FirPlatformDiagnosticSuppressor import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.hasModifier import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors @@ -18,7 +19,9 @@ import org.jetbrains.kotlin.fir.declarations.utils.isExternal import org.jetbrains.kotlin.lexer.KtTokens // See old FE's [DeclarationsChecker] -object FirTopLevelFunctionsChecker : FirSimpleFunctionChecker() { +abstract class FirTopLevelFunctionsChecker : FirSimpleFunctionChecker() { + abstract val suppressor: FirPlatformDiagnosticSuppressor + override fun check(declaration: FirSimpleFunction, context: CheckerContext, reporter: DiagnosticReporter) { // Only report on top level callable declarations if (context.containingDeclarations.size > 1) return @@ -29,7 +32,7 @@ object FirTopLevelFunctionsChecker : FirSimpleFunctionChecker() { // So, our source of truth should be the full modifier list retrieved from the source. if (declaration.hasModifier(KtTokens.ABSTRACT_KEYWORD)) return if (declaration.isExternal) return - if (!declaration.hasBody && !declaration.isExpect) { + if (!declaration.hasBody && !declaration.isExpect && suppressor.shouldReportNoBody(declaration, context)) { reporter.reportOn(source, FirErrors.NON_MEMBER_FUNCTION_NO_BODY, declaration.symbol, context) } diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeGetter.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeGetter.fir.kt deleted file mode 100644 index 1a8252eca47..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeGetter.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -// !DIAGNOSTICS: -DEPRECATION -@nativeGetter -fun String.foo(n: Int): Int? -@nativeGetter -fun String.bar(n: Int): Int? = definedExternally - - -external interface T { - @nativeGetter - fun foo(d: Double): String? - @nativeGetter - fun bar(d: Double): String? -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeGetter.kt b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeGetter.kt index 74d3cfdcae6..8bd94ee097d 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeGetter.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeGetter.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -DEPRECATION @nativeGetter fun String.foo(n: Int): Int? diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeInvoke.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeInvoke.fir.kt deleted file mode 100644 index a267f489e18..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeInvoke.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -// !DIAGNOSTICS: -DEPRECATION -@nativeInvoke -fun String.foo(): Int -@nativeInvoke -fun String.bar(): Int = definedExternally - - -external object O { - @nativeInvoke - fun foo() - @nativeInvoke - fun bar() { definedExternally } -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeInvoke.kt b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeInvoke.kt index e952b175997..63a43e7bb30 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeInvoke.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeInvoke.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -DEPRECATION @nativeInvoke fun String.foo(): Int diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeSetter.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeSetter.fir.kt deleted file mode 100644 index 912b6e581ab..00000000000 --- a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeSetter.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -// !DIAGNOSTICS: -DEPRECATION -@nativeSetter -fun String.foo(n: Int, v: Any) -@nativeSetter -fun String.bar(n: Int, v: Any) {} - - -external class C { - @nativeSetter - fun foo(d: Double, v: Any): Any - @nativeSetter - fun bar(d: Double, v: Any): Any = definedExternally -} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeSetter.kt b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeSetter.kt index d88cc88ba83..f15e8c84a12 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeSetter.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/native/optionlBody/nativeSetter.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -DEPRECATION @nativeSetter fun String.foo(n: Int, v: Any) diff --git a/core/compiler.common.js/src/org/jetbrains/kotlin/name/JsStandardClassIds.kt b/core/compiler.common.js/src/org/jetbrains/kotlin/name/JsStandardClassIds.kt index 1523be99afe..6f95d1cefca 100644 --- a/core/compiler.common.js/src/org/jetbrains/kotlin/name/JsStandardClassIds.kt +++ b/core/compiler.common.js/src/org/jetbrains/kotlin/name/JsStandardClassIds.kt @@ -22,6 +22,8 @@ object JsStandardClassIds { val JsNativeSetter = "nativeSetter".jsId() val annotationsRequiringExternal = setOf(JsModule, JsQualifier) + + val nativeAnnotations = setOf(JsNative, JsNativeInvoke, JsNativeGetter, JsNativeSetter) } object Callables {