From c05c07f2435b0c59ee58a9f1edb1365da5dd808c Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Wed, 20 Nov 2019 22:44:28 +0300 Subject: [PATCH] [JS IR] Generate special region comments at the start and the end of each file block It allows to fold these blocks and navigate to them in the IDEA. Also, this commit adds compiler configuration keys to control generating comments with paths for file blocks, and now generating such comments is enabled only in our tests. --- .../irToJs/IrModuleToJsTransformer.kt | 64 ++++++++++++++++--- .../kotlin/js/config/JSConfigurationKeys.java | 6 ++ .../jetbrains/kotlin/js/test/BasicBoxTest.kt | 13 ++-- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt index 0e829a03f36..14ad1760fe4 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt @@ -31,34 +31,52 @@ class IrModuleToJsTransformer( ) { val moduleName = backendContext.configuration[CommonConfigurationKeys.MODULE_NAME]!! private val moduleKind = backendContext.configuration[JSConfigurationKeys.MODULE_KIND]!! + private val generateRegionComments = backendContext.configuration.getBoolean(JSConfigurationKeys.GENERATE_REGION_COMMENTS) private fun generateModuleBody(module: IrModuleFragment, context: JsGenerationContext): List { val statements = mutableListOf().also { if (!generateScriptModule) it += JsStringLiteral("use strict").makeStmt() } - val preDeclarationBlock = JsBlock() - val postDeclarationBlock = JsBlock() + val preDeclarationBlock = JsGlobalBlock() + val postDeclarationBlock = JsGlobalBlock() - statements += preDeclarationBlock + statements.addWithComment("block: pre-declaration", preDeclarationBlock) + + val generateFilePaths = backendContext.configuration.getBoolean(JSConfigurationKeys.GENERATE_COMMENTS_WITH_FILE_PATH) module.files.forEach { val fileStatements = it.accept(IrFileToJsTransformer(), context).statements if (fileStatements.isNotEmpty()) { - statements.add(JsSingleLineComment("file: ${it.path}")) + var startComment = "" + + if (generateRegionComments) { + startComment = "region " + } + + if (generateRegionComments || generateFilePaths) { + startComment += "file: ${it.path}" + } + + if (startComment.isNotEmpty()) { + statements.add(JsSingleLineComment(startComment)) + } statements.addAll(fileStatements) + statements.endRegion() } } // sort member forwarding code processClassModels(context.staticContext.classModels, preDeclarationBlock, postDeclarationBlock) - statements += postDeclarationBlock - statements += context.staticContext.initializerBlock + statements.addWithComment("block: post-declaration", postDeclarationBlock.statements) + statements.addWithComment("block: init", context.staticContext.initializerBlock.statements) if (backendContext.hasTests) { + statements.startRegion("block: tests") statements += JsInvocation(context.getNameForStaticFunction(backendContext.testContainer).makeRef()).makeStmt() + statements.endRegion() } return statements @@ -108,18 +126,18 @@ class IrModuleToJsTransformer( if (generateScriptModule) { with(program.globalBlock) { - statements += importStatements + statements.addWithComment("block: imports", importStatements) statements += moduleBody - statements += exportStatements + statements.addWithComment("block: exports", exportStatements) } } else { with(rootFunction) { parameters += JsParameter(internalModuleName) parameters += importedJsModules.map { JsParameter(it.internalName) } with(body) { - statements += importStatements + statements.addWithComment("block: imports", importStatements) statements += moduleBody - statements += exportStatements + statements.addWithComment("block: exports", exportStatements) statements += generateCallToMain(rootContext) statements += JsReturn(internalModuleName.makeRef()) } @@ -229,4 +247,30 @@ class IrModuleToJsTransformer( declarationHandler ) } + + private fun MutableList.startRegion(description: String = "") { + if (generateRegionComments) { + this += JsSingleLineComment("region $description") + } + } + + private fun MutableList.endRegion() { + if (generateRegionComments) { + this += JsSingleLineComment("endregion") + } + } + + private fun MutableList.addWithComment(regionDescription: String = "", block: JsBlock) { + startRegion(regionDescription) + this += block + endRegion() + } + + private fun MutableList.addWithComment(regionDescription: String = "", statements: List) { + if (statements.isEmpty()) return + + startRegion(regionDescription) + this += statements + endRegion() + } } \ No newline at end of file diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JSConfigurationKeys.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JSConfigurationKeys.java index 3ce2cf024a1..7924b8cdde8 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JSConfigurationKeys.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JSConfigurationKeys.java @@ -75,4 +75,10 @@ public class JSConfigurationKeys { public static final CompilerConfigurationKey DEVELOPER_MODE = CompilerConfigurationKey.create("enables additional checkers"); + + public static final CompilerConfigurationKey GENERATE_COMMENTS_WITH_FILE_PATH = + CompilerConfigurationKey.create("generate comments with file path at the start of each file block"); + + public static final CompilerConfigurationKey GENERATE_REGION_COMMENTS = + CompilerConfigurationKey.create("generate special comments at the start and the end of each file block, it allows to fold them and navigate to them in the IDEA"); } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt index 09888cf3307..c3c484458c3 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt @@ -55,16 +55,15 @@ import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil import org.jetbrains.kotlin.serialization.js.ModuleKind -import org.jetbrains.kotlin.test.InTextDirectivesUtils -import org.jetbrains.kotlin.test.KotlinTestUtils -import org.jetbrains.kotlin.test.TestFiles -import org.jetbrains.kotlin.test.KotlinTestWithEnvironment -import org.jetbrains.kotlin.test.TargetBackend +import org.jetbrains.kotlin.test.* import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.JsMetadataVersion import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils -import java.io.* +import java.io.ByteArrayOutputStream +import java.io.Closeable +import java.io.File +import java.io.PrintStream import java.lang.Boolean.getBoolean import java.nio.charset.Charset import java.util.regex.Pattern @@ -672,6 +671,8 @@ abstract class BasicBoxTest( configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, typedArraysEnabled) + configuration.put(JSConfigurationKeys.GENERATE_REGION_COMMENTS, true) + return JsConfig(project, configuration, METADATA_CACHE, (JsConfig.JS_STDLIB + JsConfig.JS_KOTLIN_TEST).toSet()) }