From 0ab91821c822b36f23ae42c5b46fd63cb39a00d8 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 23 Mar 2020 12:03:56 +0300 Subject: [PATCH] Wizard: use IJ wrappers for Velocity --- .../IdeaVelocityEngineTemplateService.kt | 20 ++++ .../wizard/service/IdeaWizardService.kt | 3 +- .../core/service/TemplateEngineService.kt | 63 ++++++++++++ .../core/service/WizardService.kt | 3 +- .../plugins/templates/TemplatesPlugin.kt | 12 +-- .../projectWizard/templates/TemplateEngine.kt | 95 ------------------- 6 files changed, 93 insertions(+), 103 deletions(-) create mode 100644 idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/service/IdeaVelocityEngineTemplateService.kt create mode 100644 libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/TemplateEngineService.kt delete mode 100644 libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/TemplateEngine.kt diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/service/IdeaVelocityEngineTemplateService.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/service/IdeaVelocityEngineTemplateService.kt new file mode 100644 index 00000000000..981e872dff7 --- /dev/null +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/service/IdeaVelocityEngineTemplateService.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.tools.projectWizard.wizard.service + +import com.intellij.ide.fileTemplates.FileTemplateUtil +import org.jetbrains.kotlin.tools.projectWizard.core.service.TemplateEngineService +import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplateDescriptor +import org.jetbrains.kotlin.tools.projectWizard.templates.Template + +class IdeaVelocityEngineTemplateService : TemplateEngineService, IdeaWizardService { + override fun renderTemplate(template: FileTemplateDescriptor, data: Map): String { + val templatePath = template.templateId + val templateText = Template::class.java.getResource(templatePath).readText() + return FileTemplateUtil.mergeTemplate(data, templateText, false) + } + +} \ No newline at end of file diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/service/IdeaWizardService.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/service/IdeaWizardService.kt index ef828c66005..32e442d8634 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/service/IdeaWizardService.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/service/IdeaWizardService.kt @@ -15,7 +15,8 @@ object IdeaServices { IdeaFileSystemWizardService(), IdeaBuildSystemAvailabilityWizardService(), IdeaKotlinVersionProviderService(), - IdeaSettingSavingWizardService() + IdeaSettingSavingWizardService(), + IdeaVelocityEngineTemplateService() ) fun createScopeDependent(project: Project) = listOfNotNull( diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/TemplateEngineService.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/TemplateEngineService.kt new file mode 100644 index 00000000000..50606df6033 --- /dev/null +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/TemplateEngineService.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.tools.projectWizard.core.service + +import org.apache.velocity.VelocityContext +import org.apache.velocity.app.Velocity +import org.apache.velocity.runtime.RuntimeConstants +import org.apache.velocity.runtime.RuntimeServices +import org.apache.velocity.runtime.log.LogChute +import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult +import org.jetbrains.kotlin.tools.projectWizard.core.Writer +import org.jetbrains.kotlin.tools.projectWizard.core.div +import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplate +import org.jetbrains.kotlin.tools.projectWizard.templates.FileTemplateDescriptor +import org.jetbrains.kotlin.tools.projectWizard.templates.Template +import java.io.StringWriter + +interface TemplateEngineService : WizardService { + fun renderTemplate(template: FileTemplateDescriptor, data: Map): String + + fun Writer.writeTemplate(template: FileTemplate): TaskResult { + val formatter = service() + val text = renderTemplate(template.descriptor, template.data).let { text -> + formatter.formatFile(text, template.descriptor.relativePath.fileName.toString()) + } + return service().createFile(template.rootPath / template.descriptor.relativePath, text) + } +} + + +class VelocityTemplateEngineServiceImpl : TemplateEngineService, IdeaIndependentWizardService { + override fun renderTemplate(template: FileTemplateDescriptor, data: Map): String { + val templatePath = template.templateId + val templateText = Template::class.java.getResource(templatePath).readText() + val context = VelocityContext().apply { + data.forEach { (key, value) -> put(key, value) } + } + return StringWriter().use { writer -> + runVelocityActionWithoutLogging { Velocity.evaluate(context, writer, "", templateText) } + writer.toString() + } + } + + + private fun runVelocityActionWithoutLogging(action: () -> Unit) { + val initialLogger = Velocity.getProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM) + Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, DoNothingVelocityLogger) + action() + if (initialLogger != null) { + Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, initialLogger) + } + } + + private object DoNothingVelocityLogger : LogChute { + override fun isLevelEnabled(level: Int): Boolean = false + override fun init(rs: RuntimeServices?) = Unit + override fun log(level: Int, message: String?) = Unit + override fun log(level: Int, message: String?, t: Throwable?) = Unit + } +} \ No newline at end of file diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/WizardService.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/WizardService.kt index d6e74228874..366280794ab 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/WizardService.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/core/service/WizardService.kt @@ -12,7 +12,8 @@ object Services { DummyFileFormattingService(), KotlinVersionProviderServiceImpl(), RunConfigurationsServiceImpl(), - SettingSavingWizardServiceImpl() + SettingSavingWizardServiceImpl(), + VelocityTemplateEngineServiceImpl() ) } diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/TemplatesPlugin.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/TemplatesPlugin.kt index 9ecdf60c072..f506024b7c2 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/TemplatesPlugin.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/plugins/templates/TemplatesPlugin.kt @@ -5,6 +5,7 @@ import org.jetbrains.kotlin.tools.projectWizard.core.* import org.jetbrains.kotlin.tools.projectWizard.core.Defaults.KOTLIN_DIR import org.jetbrains.kotlin.tools.projectWizard.core.Defaults.RESOURCES_DIR import org.jetbrains.kotlin.tools.projectWizard.core.Defaults.SRC_DIR +import org.jetbrains.kotlin.tools.projectWizard.core.service.TemplateEngineService import org.jetbrains.kotlin.tools.projectWizard.ir.buildsystem.* import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemPlugin @@ -44,7 +45,7 @@ class TemplatesPlugin(context: Context) : Plugin(context) { val renderFileTemplates by pipelineTask(GenerationPhase.PROJECT_GENERATION) { runAfter(KotlinPlugin::createModules) withAction { - val templateEngine = VelocityTemplateEngine() + val templateEngine = service() TemplatesPlugin::fileTemplatesToRender.propertyValue.mapSequenceIgnore { template -> with(templateEngine) { writeTemplate(template) } } @@ -56,7 +57,6 @@ class TemplatesPlugin(context: Context) : Plugin(context) { runAfter(KotlinPlugin::createModules) withAction { - val templateEngine = VelocityTemplateEngine() updateBuildFiles { buildFile -> buildFile.modules.modules.mapSequence { module -> applyTemplateToModule( @@ -90,11 +90,11 @@ class TemplatesPlugin(context: Context) : Plugin(context) { val modules = buildFile.modules.modules val applicationState = modules.mapNotNull { module -> - module.template?.createInterceptors(module) - }.flatten() + module.template?.createInterceptors(module) + }.flatten() .applyAll(TemplateInterceptionApplicationState(buildFile, emptyMap())) - val templateEngine = VelocityTemplateEngine() + val templateEngine = service() val templatesApplicationResult = modules.map { module -> val settings = applicationState.moduleToSettings[module.originalModule.identificator].orEmpty() @@ -108,7 +108,7 @@ class TemplatesPlugin(context: Context) : Plugin(context) { private fun Writer.applyFileTemplatesFromSourceset( module: ModuleIR, - templateEngine: TemplateEngine, + templateEngine: TemplateEngineService, interceptionPointSettings: Map, Any> ): TaskResult { val template = module.template ?: return UNIT_SUCCESS diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/TemplateEngine.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/TemplateEngine.kt deleted file mode 100644 index ab32d05a305..00000000000 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/templates/TemplateEngine.kt +++ /dev/null @@ -1,95 +0,0 @@ -package org.jetbrains.kotlin.tools.projectWizard.templates - -import org.apache.velocity.VelocityContext -import org.apache.velocity.app.Velocity -import org.apache.velocity.runtime.RuntimeConstants -import org.apache.velocity.runtime.RuntimeServices -import org.apache.velocity.runtime.log.LogChute -import org.jetbrains.kotlin.tools.projectWizard.core.TaskResult -import org.jetbrains.kotlin.tools.projectWizard.core.Writer - -import org.jetbrains.kotlin.tools.projectWizard.core.div -import org.jetbrains.kotlin.tools.projectWizard.core.service.FileFormattingService -import org.jetbrains.kotlin.tools.projectWizard.core.service.FileSystemWizardService -import java.io.StringWriter - - -interface TemplateEngine { - fun renderTemplate(template: FileTemplateDescriptor, data: Map): String - - fun Writer.writeTemplate(template: FileTemplate): TaskResult { - val formatter = service() - val text = renderTemplate(template.descriptor, template.data).let { text -> - formatter.formatFile(text, template.descriptor.relativePath.fileName.toString()) - } - return service().createFile(template.rootPath / template.descriptor.relativePath, text) - } -} - -class VelocityTemplateEngine : TemplateEngine { - override fun renderTemplate(template: FileTemplateDescriptor, data: Map): String { - val templatePath = template.templateId - val templateText = try { - VelocityTemplateEngine::class.java.getResource(templatePath).readText() - } catch (e: Throwable) { - throw e - } - val context = VelocityContext().apply { - data.forEach { (key, value) -> - put(key, value) - } - } - return StringWriter().use { writer -> - runVelocityActionWithoutLogging { Velocity.evaluate(context, writer, "", templateText) } - writer.toString() - } - } - - private fun runVelocityActionWithoutLogging(action: () -> Unit) { - val initialLogger = Velocity.getProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM) - Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, DO_NOTHING_VELOCITY_LOGGER) - action() - if (initialLogger != null) { - Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, initialLogger) - } - } - - companion object { - private val DO_NOTHING_VELOCITY_LOGGER = object : LogChute { - override fun isLevelEnabled(level: Int): Boolean = false - override fun init(rs: RuntimeServices?) = Unit - override fun log(level: Int, message: String?) = Unit - override fun log(level: Int, message: String?, t: Throwable?) = Unit - } - } -} -// -//object TemplateEngineHelper { -// fun getAllFileTemplatesByPath(path: Path, resultedPath: Path, settings: Map): List { -// val rootUri = VelocityTemplateEngine::class.java.getResource(path.toString()).toURI() -// return getFileSystem(rootUri).use { fileSystem -> -// val rootPath = fileSystem.rootDirectories.firstOrNull() ?: return@use emptyList() -// val resourcePath = VelocityTemplateEngine::class.resourcesDirPath(rootPath) -// Files.walk(resourcePath / path.toString()) -// .filter { path -> -// Files.isRegularFile(path) && path.fileName.toString().endsWith(".vm") -// }.map { file -> -// val relativePath = resourcePath.relativize(file) -// val templateDescriptor = FileTemplateDescriptor( -// relativePath.toString(), -// resourcePath.relativize(resourcePath / path.toString()) -// ) -// FileTemplate(templateDescriptor, resultedPath, settings) -// }.collect(Collectors.toList()) -// } -// } -// -// private fun KClass.resourcesDirPath(rootPath: Path) = -// java.`package`.name.split(".").fold(rootPath, Path::resolve) -// -// private fun getFileSystem(uri: URI): FileSystem = try { -// FileSystems.getFileSystem(uri) -// } catch (e: FileSystemNotFoundException) { -// FileSystems.newFileSystem(uri, emptyMap()) -// } -//}