diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/library/a.kt new file mode 100644 index 00000000000..2dc03d6b5da --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/library/a.kt @@ -0,0 +1,11 @@ +package a + +open class A { + class Nested + + fun method() {} +} + +fun foo() {} +var bar = 42 +typealias TA = String diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/output.txt new file mode 100644 index 00000000000..f5558cfe828 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/output.txt @@ -0,0 +1,2 @@ +error: file '$TMP_DIR$/library.meta.js' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 42.0.0, expected version is 1.0.0 +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/source.kt new file mode 100644 index 00000000000..f15b2e0bd70 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJs/source.kt @@ -0,0 +1,15 @@ +package usage + +import a.* + +fun baz(param: A, nested: A.Nested) { + val constructor = A() + val nested = A.Nested() + val methodCall = param.method() + val supertype = object : A() {} + + val x = foo() + val y = bar + bar = 239 + val z: TA = "" +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/library/a.kt new file mode 100644 index 00000000000..2dc03d6b5da --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/library/a.kt @@ -0,0 +1,11 @@ +package a + +open class A { + class Nested + + fun method() {} +} + +fun foo() {} +var bar = 42 +typealias TA = String diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/output.txt new file mode 100644 index 00000000000..a0aba9318ad --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/output.txt @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/source.kt new file mode 100644 index 00000000000..cf47e098fb1 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/wrongMetadataVersionJsSkipVersionCheck/source.kt @@ -0,0 +1,16 @@ +@file:Suppress("UNUSED_VARIABLE", "UNUSED_PARAMETER") +package usage + +import a.* + +fun baz(param: A, nested: A.Nested) { + val constructor = A() + val nested2 = A.Nested() + val methodCall = param.method() + val supertype = object : A() {} + + val x = foo() + val y = bar + bar = 239 + val z: TA = "" +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java index c17039bbe1a..7963821cda0 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.java @@ -25,6 +25,7 @@ import kotlin.Pair; import kotlin.collections.SetsKt; import kotlin.io.FilesKt; import kotlin.jvm.functions.Function2; +import kotlin.text.Charsets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.analyzer.AnalysisResult; @@ -52,6 +53,7 @@ import org.jetbrains.kotlin.test.*; import org.jetbrains.kotlin.test.util.DescriptorValidator; import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator; import org.jetbrains.kotlin.utils.ExceptionUtilsKt; +import org.jetbrains.kotlin.utils.JsMetadataVersion; import org.jetbrains.kotlin.utils.StringsKt; import org.jetbrains.org.objectweb.asm.ClassReader; import org.jetbrains.org.objectweb.asm.ClassVisitor; @@ -316,6 +318,21 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { KotlinTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), normalizeOutput(output)); } + private void doTestKotlinLibraryWithWrongMetadataVersionJs(@NotNull String libraryName, @NotNull String... additionalOptions) { + compileLibrary(new K2JSCompiler(), libraryName, new File(tmpdir, "library.js"), Collections.emptyList()); + + File library = new File(tmpdir, "library.meta.js"); + FilesKt.writeText(library, FilesKt.readText(library, Charsets.UTF_8).replace( + "(" + JsMetadataVersion.INSTANCE.toInteger() + ", ", + "(" + new JsMetadataVersion(42, 0, 0).toInteger() + ", " + ), Charsets.UTF_8); + + Pair output = compileKotlin( + new K2JSCompiler(), "source.kt", new File(tmpdir, "usage.js"), Arrays.asList(additionalOptions), library + ); + KotlinTestUtils.assertEqualsToFile(new File(getTestDataDirectory(), "output.txt"), normalizeOutput(output)); + } + private void doTestPreReleaseKotlinLibrary( @NotNull CLICompiler compiler, @NotNull String libraryName, @@ -492,6 +509,10 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { doTestKotlinLibraryWithWrongMetadataVersion("library", null); } + public void testWrongMetadataVersionJs() throws Exception { + doTestKotlinLibraryWithWrongMetadataVersionJs("library"); + } + public void testWrongMetadataVersionBadMetadata() throws Exception { doTestKotlinLibraryWithWrongMetadataVersion( "library", @@ -532,6 +553,10 @@ public class CompileKotlinAgainstCustomBinariesTest extends TestCaseWithTmpdir { doTestKotlinLibraryWithWrongMetadataVersion("library", null, "-Xskip-metadata-version-check"); } + public void testWrongMetadataVersionJsSkipVersionCheck() throws Exception { + doTestKotlinLibraryWithWrongMetadataVersionJs("library", "-Xskip-metadata-version-check"); + } + /*test source mapping generation when source info is absent*/ public void testInlineFunWithoutDebugInfo() throws Exception { compileKotlin("sourceInline.kt", tmpdir); diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt index 68e69db9eaf..b78ac922e9a 100644 --- a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt +++ b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt @@ -393,7 +393,7 @@ class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() { val warnings = buildResult.getMessages(BuildMessage.Kind.WARNING) assertEquals("Warning about duplicate module definition: $warnings", 1, warnings.size) - assertEquals("Module \"srcAndTests\" is defined in more, than one file", warnings[0].messageText) + assertEquals("Module \"srcAndTests\" is defined in more than one file", warnings[0].messageText) } fun testKotlinJavaScriptProjectWithTwoSrcModuleDependency() { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java index b17945e4ab5..aa8d2ca2867 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java @@ -21,9 +21,7 @@ import com.intellij.util.SmartList; import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.config.CommonConfigurationKeys; -import org.jetbrains.kotlin.config.CommonConfigurationKeysKt; -import org.jetbrains.kotlin.config.CompilerConfiguration; +import org.jetbrains.kotlin.config.*; import org.jetbrains.kotlin.descriptors.PackageFragmentProvider; import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl; import org.jetbrains.kotlin.js.resolve.JsPlatform; @@ -121,7 +119,9 @@ public abstract class JsConfig { } private JsModuleDescriptor createModuleDescriptor(KotlinJavascriptMetadata metadata) { - assert metadata.getVersion().isCompatible() : + LanguageVersionSettings languageVersionSettings = CommonConfigurationKeysKt.getLanguageVersionSettings(configuration); + assert metadata.getVersion().isCompatible() || + languageVersionSettings.isFlagEnabled(AnalysisFlags.getSkipMetadataVersionCheck()) : "Expected JS metadata version " + JsMetadataVersion.INSTANCE + ", but actual metadata version is " + metadata.getVersion(); ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl( @@ -130,7 +130,7 @@ public abstract class JsConfig { JsModuleDescriptor rawDescriptor = KotlinJavascriptSerializationUtil.readModule( metadata.getBody(), storageManager, moduleDescriptor, - new CompilerDeserializationConfiguration(CommonConfigurationKeysKt.getLanguageVersionSettings(configuration)) + new CompilerDeserializationConfiguration(languageVersionSettings) ); PackageFragmentProvider provider = rawDescriptor.getData(); diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java index 67863f338cd..ea1b6605efc 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java @@ -27,6 +27,7 @@ import kotlin.Unit; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.config.AnalysisFlags; import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.utils.JsMetadataVersion; import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata; @@ -38,6 +39,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import static org.jetbrains.kotlin.config.CommonConfigurationKeysKt.getLanguageVersionSettings; import static org.jetbrains.kotlin.utils.PathUtil.getKotlinPathsForDistDirectory; public class LibrarySourcesConfig extends JsConfig { @@ -100,6 +102,9 @@ public class LibrarySourcesConfig extends JsConfig { Set modules = new HashSet(); + boolean skipMetadataVersionCheck = + getLanguageVersionSettings(getConfiguration()).isFlagEnabled(AnalysisFlags.getSkipMetadataVersionCheck()); + for (String path : libraries) { VirtualFile file; @@ -128,15 +133,16 @@ public class LibrarySourcesConfig extends JsConfig { } for (KotlinJavascriptMetadata metadata : metadataList) { - if (!metadata.getVersion().isCompatible()) { + if (!metadata.getVersion().isCompatible() && !skipMetadataVersionCheck) { report.error("File '" + path + "' was compiled with an incompatible version of Kotlin. " + - "The binary version of its metadata is " + metadata.getVersion() + - ", expected version is " + JsMetadataVersion.INSTANCE); + "The binary version of its metadata is " + metadata.getVersion() + + ", expected version is " + JsMetadataVersion.INSTANCE); return true; } if (!modules.add(metadata.getModuleName())) { - report.warning("Module \"" + metadata.getModuleName() + "\" is defined in more, than one file"); - }} + report.warning("Module \"" + metadata.getModuleName() + "\" is defined in more than one file"); + } + } if (action != null) { action.invoke(file);