From 18bfe5b1ad39576dd3f6a4b53cb3d9842bfb3289 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Thu, 26 Jun 2025 17:08:42 +0200 Subject: [PATCH] Add a test for consistency between JavaSyntaxBundle and DefaultJavaSyntaxResources, document the regeneration process GitOrigin-RevId: 1569c0a8a0a372bbba547273a0076ed389a50164 --- .../intellij/java/syntax/JavaSyntaxBundle.kt | 8 +++ java/java-tests/BUILD.bazel | 1 + java/java-tests/intellij.java.tests.iml | 1 + .../syntax/DefaultJavaSyntaxResourcesTest.kt | 19 +++++++ .../syntax-scripts/api-dump-experimental.txt | 1 + .../syntax/scripts/generateBundleMapping.kt | 54 +++++++++++++++---- 6 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/java/tests/syntax/DefaultJavaSyntaxResourcesTest.kt diff --git a/java/java-syntax/src/com/intellij/java/syntax/JavaSyntaxBundle.kt b/java/java-syntax/src/com/intellij/java/syntax/JavaSyntaxBundle.kt index 85a10548a117..0de8eac02cfc 100644 --- a/java/java-syntax/src/com/intellij/java/syntax/JavaSyntaxBundle.kt +++ b/java/java-syntax/src/com/intellij/java/syntax/JavaSyntaxBundle.kt @@ -6,6 +6,7 @@ import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.Nls import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.PropertyKey +import org.jetbrains.annotations.VisibleForTesting import kotlin.jvm.JvmStatic @ApiStatus.Internal @@ -32,3 +33,10 @@ object JavaSyntaxBundle { return resourceBundle.messagePointer(key, *params) } } + +@VisibleForTesting +@ApiStatus.Internal +object DefaultJavaSyntaxResourcesTestAccessor { + val mappings: Map get() = DefaultJavaSyntaxResources.mappings + val defaultJavaSyntaxResourcesName: String get() = DefaultJavaSyntaxResources::class.java.name +} diff --git a/java/java-tests/BUILD.bazel b/java/java-tests/BUILD.bazel index c0b5900c7f6f..ad9fdfadefc0 100644 --- a/java/java-tests/BUILD.bazel +++ b/java/java-tests/BUILD.bazel @@ -153,6 +153,7 @@ jvm_library( "//java/java-syntax:syntax", "//platform/lang-impl", "//xml/impl", + "//platform/syntax/syntax-scripts:scripts", ], runtime_deps = [ ":tests_test_resources", diff --git a/java/java-tests/intellij.java.tests.iml b/java/java-tests/intellij.java.tests.iml index eb671d860a21..554ff0825787 100644 --- a/java/java-tests/intellij.java.tests.iml +++ b/java/java-tests/intellij.java.tests.iml @@ -127,5 +127,6 @@ + \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/tests/syntax/DefaultJavaSyntaxResourcesTest.kt b/java/java-tests/testSrc/com/intellij/java/tests/syntax/DefaultJavaSyntaxResourcesTest.kt new file mode 100644 index 000000000000..5ed91b3261d3 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/tests/syntax/DefaultJavaSyntaxResourcesTest.kt @@ -0,0 +1,19 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.java.tests.syntax + +import com.intellij.java.syntax.DefaultJavaSyntaxResourcesTestAccessor +import com.intellij.java.syntax.JavaSyntaxBundle +import com.intellij.platform.syntax.scripts.assertPropertiesMatch +import org.junit.jupiter.api.Test + +class DefaultJavaSyntaxResourcesTest { + @Test + fun testJavaSyntaxResourcesMatch() { + assertPropertiesMatch( + propertiesFileName = JavaSyntaxBundle.BUNDLE, + defaultResourcesFileName = DefaultJavaSyntaxResourcesTestAccessor.defaultJavaSyntaxResourcesName, + classLoader = JavaSyntaxBundle.javaClass.classLoader, + actualMapping = DefaultJavaSyntaxResourcesTestAccessor.mappings, + ) + } +} \ No newline at end of file diff --git a/platform/syntax/syntax-scripts/api-dump-experimental.txt b/platform/syntax/syntax-scripts/api-dump-experimental.txt index 75e04b903bbf..da6adcb0ddf1 100644 --- a/platform/syntax/syntax-scripts/api-dump-experimental.txt +++ b/platform/syntax/syntax-scripts/api-dump-experimental.txt @@ -1,3 +1,4 @@ *f:com.intellij.platform.syntax.scripts.GenerateBundleMappingKt +- sf:assertPropertiesMatch(java.lang.String,java.lang.String,java.lang.ClassLoader,java.util.Map):V - sf:generateMapping(java.lang.String,java.lang.String,java.lang.String):V - sf:main(java.lang.String[]):V diff --git a/platform/syntax/syntax-scripts/src/com/intellij/platform/syntax/scripts/generateBundleMapping.kt b/platform/syntax/syntax-scripts/src/com/intellij/platform/syntax/scripts/generateBundleMapping.kt index c8a36563afbc..ddafbec25fa7 100644 --- a/platform/syntax/syntax-scripts/src/com/intellij/platform/syntax/scripts/generateBundleMapping.kt +++ b/platform/syntax/syntax-scripts/src/com/intellij/platform/syntax/scripts/generateBundleMapping.kt @@ -49,7 +49,7 @@ fun generateMapping( outputPath.createFile() } - val mappings = loadMappings(propertiesPath) + val mappings = loadMappingsFromFile(propertiesPath) val fileName = outputPath.nameWithoutExtension outputPath.writer().buffered().use { writer -> @@ -59,6 +59,30 @@ fun generateMapping( println("Done! Result: $outputPath") } +/** + * Use to ensure the properties file and the default resources file are in sync. + */ +fun assertPropertiesMatch( + propertiesFileName: String, + defaultResourcesFileName: String, + classLoader: ClassLoader, + actualMapping: Map, +) { + val propResourceName = propertiesFileName.asResourceName() + val propertiesFileStream = classLoader.getResourceAsStream(propResourceName)!! + val expectedMapping = propertiesFileStream.use { stream -> + loadPropertiesBundleMappings(stream) + } + + require(expectedMapping == actualMapping) { + """ + |$propertiesFileName and $defaultResourcesFileName do not match. + | + |Please regenerate $defaultResourcesFileName. See instruction how to do it in the class's doc. + """.trimMargin() + } +} + private fun Writer.printClass( className: String, packageName: String, @@ -67,9 +91,7 @@ private fun Writer.printClass( ) { appendLine("package $packageName") appendLine() - appendLine("// Generated by generateBundleMapping.kt") - appendLine("// To regenerate the file, please run `GenerateBundleMapping` run configuration with the following parameters: ") - appendLine("// $parametersString ") + appendLine(getRegenerationInstruction(parametersString).addLinePrefix("// ")) appendLine("internal object $className {") appendLine(" val mappings: Map = mapOf(") for ((key, value) in mappings.entries.sortedBy { it.key }) { @@ -84,13 +106,27 @@ private fun Writer.printClass( appendLine('}') } -private fun loadMappings(propertiesPath: Path): Map { - val properties = Properties() - propertiesPath.inputStream().use { stream -> - properties.load(stream) - } +private fun getRegenerationInstruction(parametersString: String): String { + return """ + To regenerate the file, please run `GenerateBundleMapping` run configuration with the following parameters: ") + $parametersString + """.trimIndent() +} +private fun String.addLinePrefix(linePrefix: String): String = split('\n').joinToString("\n") { "$linePrefix$it" } + +private fun loadMappingsFromFile(propertiesPath: Path): Map { + propertiesPath.inputStream().buffered().use { stream -> + return loadPropertiesBundleMappings(stream) + } +} + +private fun loadPropertiesBundleMappings(stream: InputStream): Map { + val properties = Properties() + properties.load(stream) return properties.entries.associate { (key, value) -> (key as String) to (value as String) } } + +private fun String.asResourceName(): String = object : ResourceBundle.Control() {}.toResourceName(this, "properties")