From 3f2ec6871dc677b4c2348279e4894e2a8ce92557 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Wed, 29 Jun 2016 16:39:43 +0300 Subject: [PATCH] KT-12877: add some front-end diagnostics for JsModule --- .../module/jsVarProhibited.kt | 3 ++ .../module/jsVarProhibited.txt | 5 +++ .../module/prohibitedOnNonNative.kt | 9 ++++ .../module/prohibitedOnNonNative.txt | 20 +++++++++ .../DiagnosticsTestWithJsStdLibGenerated.java | 21 +++++++++ .../js/resolve/JsPlatformConfigurator.kt | 2 +- .../diagnostics/DefaultErrorMessagesJs.kt | 2 + .../js/resolve/diagnostics/ErrorsJs.java | 2 + .../js/resolve/diagnostics/JsModuleChecker.kt | 44 +++++++++++++++++++ 9 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.txt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.txt create mode 100644 js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsModuleChecker.kt diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.kt b/compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.kt new file mode 100644 index 00000000000..c215d0904a5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.kt @@ -0,0 +1,3 @@ +package foo + +@JsModule("bar") @native var baz: Int = noImpl \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.txt b/compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.txt new file mode 100644 index 00000000000..539d422bfc5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.txt @@ -0,0 +1,5 @@ +package + +package foo { + @kotlin.js.JsModule(import = "bar") @kotlin.js.native public var baz: kotlin.Int +} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.kt b/compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.kt new file mode 100644 index 00000000000..10bc482228d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.kt @@ -0,0 +1,9 @@ +package foo + +@JsModule("A") class A + +@JsModule("B") object B + +@JsModule("foo") fun foo() = 23 + +@JsModule("bar") val bar = 42 \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.txt b/compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.txt new file mode 100644 index 00000000000..988cff6076c --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.txt @@ -0,0 +1,20 @@ +package + +package foo { + @kotlin.js.JsModule(import = "bar") public val bar: kotlin.Int = 42 + @kotlin.js.JsModule(import = "foo") public fun foo(): kotlin.Int + + @kotlin.js.JsModule(import = "A") public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + @kotlin.js.JsModule(import = "B") public object B { + private constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index 4804f046098..dc0ab31bc1b 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -297,6 +297,27 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes } } + @TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/module") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Module extends AbstractDiagnosticsTestWithJsStdLib { + public void testAllFilesPresentInModule() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib/module"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("jsVarProhibited.kt") + public void testJsVarProhibited() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/module/jsVarProhibited.kt"); + doTest(fileName); + } + + @TestMetadata("prohibitedOnNonNative.kt") + public void testProhibitedOnNonNative() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/module/prohibitedOnNonNative.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt index d9d878ebc8c..28b55e5799b 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt @@ -34,7 +34,7 @@ object JsPlatformConfigurator : PlatformConfigurator( DynamicTypesAllowed(), additionalDeclarationCheckers = listOf( NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(), NativeInnerClassChecker(), - JsNameChecker, + JsNameChecker, JsModuleChecker, PlatformImplDeclarationChecker() ), additionalCallCheckers = listOf(ReifiedTypeParameterSubstitutionChecker()), diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/DefaultErrorMessagesJs.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/DefaultErrorMessagesJs.kt index dd6b2b060ab..1a39d1108d2 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/DefaultErrorMessagesJs.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/DefaultErrorMessagesJs.kt @@ -48,6 +48,8 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy { put(ErrorsJs.JS_NAME_PROHIBITED_FOR_OVERRIDE, "@JsName is prohibited for overridden members") put(ErrorsJs.JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY, "@JsName is prohibited for extension properties") put(ErrorsJs.JS_NAME_PROHIBITED_FOR_NAMED_NATIVE, "@JsName is prohibited for @native declaration with explicit name") + put(ErrorsJs.JS_MODULE_PROHIBITED_ON_VAR, "@JsModule annotation prohibited for 'var' declarations. Use 'val' instead.") + put(ErrorsJs.JS_MODULE_PROHIBITED_ON_NON_NATIVE, "@JsModule annotation prohibited for non-@native declarations.") put(ErrorsJs.CANNOT_CHECK_FOR_NATIVE_INTERFACE, "Cannot check for native interface: {0}", RENDER_TYPE) put(ErrorsJs.UNCHECKED_CAST_TO_NATIVE_INTERFACE, "Unchecked cast to native interface: {0} to {1}", RENDER_TYPE, RENDER_TYPE) put(ErrorsJs.NATIVE_INTERFACE_AS_REIFIED_TYPE_ARGUMENT, "Cannot pass native interface {0} for reified type parameter", RENDER_TYPE) diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/ErrorsJs.java b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/ErrorsJs.java index 8a93845a89e..a9a4cf73973 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/ErrorsJs.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/ErrorsJs.java @@ -52,6 +52,8 @@ public interface ErrorsJs { DiagnosticFactory0 JS_NAME_PROHIBITED_FOR_OVERRIDE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 JS_NAME_PROHIBITED_FOR_NAMED_NATIVE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 JS_MODULE_PROHIBITED_ON_VAR = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT); + DiagnosticFactory0 JS_MODULE_PROHIBITED_ON_NON_NATIVE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT); DiagnosticFactory1 CANNOT_CHECK_FOR_NATIVE_INTERFACE = DiagnosticFactory1.create(ERROR); DiagnosticFactory2 UNCHECKED_CAST_TO_NATIVE_INTERFACE = DiagnosticFactory2.create(WARNING); DiagnosticFactory1 NATIVE_INTERFACE_AS_REIFIED_TYPE_ARGUMENT = DiagnosticFactory1.create(ERROR); diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsModuleChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsModuleChecker.kt new file mode 100644 index 00000000000..063ccc56002 --- /dev/null +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsModuleChecker.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.resolve.diagnostics + +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker + +object JsModuleChecker : SimpleDeclarationChecker { + override fun check( + declaration: KtDeclaration, + descriptor: DeclarationDescriptor, + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext + ) { + val moduleName = AnnotationsUtils.getModuleName(descriptor) + + if (moduleName != null && descriptor is PropertyDescriptor && descriptor.isVar) { + diagnosticHolder.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_VAR.on(declaration)) + } + + if (moduleName != null && !AnnotationsUtils.isNativeObject(descriptor)) { + diagnosticHolder.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_NON_NATIVE.on(declaration)) + } + } +}