From 43cef114c6e9935436c899e8e29236f0110bad1b Mon Sep 17 00:00:00 2001 From: Alexander Korepanov Date: Tue, 14 Feb 2023 12:38:56 +0100 Subject: [PATCH] [Compiler CLI] Sort flags and features before appending them to string JS IR BE incremental compilation infrastructure uses LanguageVersionSettings::toString method to detect if any compiler features or flags were enabled or disabled. It is important that the features and flags order are stable in the result string. ^KT-56580 Fixed --- .../ir/backend/js/ic/HashCalculatorForIC.kt | 3 ++ .../kotlin/config/LanguageVersionSettings.kt | 4 +-- .../JsIrES6InvalidationTestGenerated.java | 5 ++++ .../JsIrInvalidationTestGenerated.java | 5 ++++ .../languageVersionSettings/lib1/l1.kt | 1 + .../languageVersionSettings/lib1/module.info | 6 ++++ .../languageVersionSettings/main/m.kt | 7 +++++ .../languageVersionSettings/main/module.info | 10 +++++++ .../languageVersionSettings/project.info | 30 +++++++++++++++++++ 9 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 js/js.translator/testData/incremental/invalidation/languageVersionSettings/lib1/l1.kt create mode 100644 js/js.translator/testData/incremental/invalidation/languageVersionSettings/lib1/module.info create mode 100644 js/js.translator/testData/incremental/invalidation/languageVersionSettings/main/m.kt create mode 100644 js/js.translator/testData/incremental/invalidation/languageVersionSettings/main/module.info create mode 100644 js/js.translator/testData/incremental/invalidation/languageVersionSettings/project.info diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/HashCalculatorForIC.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/HashCalculatorForIC.kt index c8e6bfdf806..42361b6a559 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/HashCalculatorForIC.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/HashCalculatorForIC.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.ic import org.jetbrains.kotlin.backend.common.serialization.Hash128Bits import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.CrossModuleReferences import org.jetbrains.kotlin.ir.IrElement @@ -87,6 +88,8 @@ internal class ICHasher { private val hashCalculator = HashCalculatorForIC() fun calculateConfigHash(config: CompilerConfiguration): ICHash { + hashCalculator.update(KotlinCompilerVersion.VERSION) + val importantSettings = listOf( JSConfigurationKeys.GENERATE_DTS, JSConfigurationKeys.MODULE_KIND, diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 0c59ccb7a18..b73e4cb78ac 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -538,7 +538,7 @@ class LanguageVersionSettingsImpl @JvmOverloads constructor( override fun toString() = buildString { append("Language = $languageVersion, API = $apiVersion") - specificFeatures.forEach { (feature, state) -> + specificFeatures.entries.sortedBy { (feature, _) -> feature.ordinal }.forEach { (feature, state) -> val char = when (state) { LanguageFeature.State.ENABLED -> '+' LanguageFeature.State.ENABLED_WITH_WARNING -> '~' @@ -546,7 +546,7 @@ class LanguageVersionSettingsImpl @JvmOverloads constructor( } append(" $char$feature") } - analysisFlags.forEach { (flag, value) -> + analysisFlags.entries.sortedBy { (flag, _) -> flag.toString() }.forEach { (flag, value) -> append(" $flag:$value") } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/JsIrES6InvalidationTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/JsIrES6InvalidationTestGenerated.java index 4e27816da92..415c18f9127 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/JsIrES6InvalidationTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/JsIrES6InvalidationTestGenerated.java @@ -255,6 +255,11 @@ public class JsIrES6InvalidationTestGenerated extends AbstractJsIrES6Invalidatio runTest("js/js.translator/testData/incremental/invalidation/jsModuleAnnotation/"); } + @TestMetadata("languageVersionSettings") + public void testLanguageVersionSettings() throws Exception { + runTest("js/js.translator/testData/incremental/invalidation/languageVersionSettings/"); + } + @TestMetadata("localInlineFunction") public void testLocalInlineFunction() throws Exception { runTest("js/js.translator/testData/incremental/invalidation/localInlineFunction/"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/JsIrInvalidationTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/JsIrInvalidationTestGenerated.java index 8807ff5d38f..420db0724ea 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/JsIrInvalidationTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/incremental/JsIrInvalidationTestGenerated.java @@ -255,6 +255,11 @@ public class JsIrInvalidationTestGenerated extends AbstractJsIrInvalidationTest runTest("js/js.translator/testData/incremental/invalidation/jsModuleAnnotation/"); } + @TestMetadata("languageVersionSettings") + public void testLanguageVersionSettings() throws Exception { + runTest("js/js.translator/testData/incremental/invalidation/languageVersionSettings/"); + } + @TestMetadata("localInlineFunction") public void testLocalInlineFunction() throws Exception { runTest("js/js.translator/testData/incremental/invalidation/localInlineFunction/"); diff --git a/js/js.translator/testData/incremental/invalidation/languageVersionSettings/lib1/l1.kt b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/lib1/l1.kt new file mode 100644 index 00000000000..9ef0f8b7e11 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/lib1/l1.kt @@ -0,0 +1 @@ +fun demo() = 42 diff --git a/js/js.translator/testData/incremental/invalidation/languageVersionSettings/lib1/module.info b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/lib1/module.info new file mode 100644 index 00000000000..65006af8d0b --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/lib1/module.info @@ -0,0 +1,6 @@ +STEP 0..3: + added file: l1.kt +STEP 4..5: +STEP 6: + added file: l1.kt +STEP 7: diff --git a/js/js.translator/testData/incremental/invalidation/languageVersionSettings/main/m.kt b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/main/m.kt new file mode 100644 index 00000000000..4c45e2b7129 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/main/m.kt @@ -0,0 +1,7 @@ +fun box(stepId: Int): String { + when (stepId) { + in 0..7 -> if (demo() != 42) return "Fail" + else -> return "Unknown" + } + return "OK" +} diff --git a/js/js.translator/testData/incremental/invalidation/languageVersionSettings/main/module.info b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/main/module.info new file mode 100644 index 00000000000..2da8a322f8e --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/main/module.info @@ -0,0 +1,10 @@ +STEP 0..3: + dependencies: lib1 + added file: m.kt +STEP 4..5: + dependencies: lib1 +STEP 6: + dependencies: lib1 + added file: m.kt +STEP 7: + dependencies: lib1 diff --git a/js/js.translator/testData/incremental/invalidation/languageVersionSettings/project.info b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/project.info new file mode 100644 index 00000000000..43a103790a2 --- /dev/null +++ b/js/js.translator/testData/incremental/invalidation/languageVersionSettings/project.info @@ -0,0 +1,30 @@ +MODULES: lib1, main + +STEP 0: + libs: lib1, main + dirty js: lib1, main +STEP 1: + language: +TypeAliases + libs: lib1, main + dirty js: lib1, main +STEP 2: + language: +TypeAliases, +BoundCallableReferences, +LocalDelegatedProperties, +TopLevelSealedInheritance + libs: lib1, main + dirty js: lib1, main +STEP 3: + language: +TypeAliases, +BoundCallableReferences, +TopLevelSealedInheritance + libs: lib1, main + dirty js: lib1, main +STEP 4: + language: +BoundCallableReferences, +TopLevelSealedInheritance, +TypeAliases + libs: lib1, main +STEP 5: + language: +BoundCallableReferences, +TypeAliases, +TopLevelSealedInheritance + libs: lib1, main +STEP 6: + language: +BoundCallableReferences, -TypeAliases, +TopLevelSealedInheritance + libs: lib1, main + dirty js: lib1, main +STEP 7: + language: +TopLevelSealedInheritance, +BoundCallableReferences, +TypeAliases + libs: lib1, main