Wizard: use IJ wrappers for Velocity

This commit is contained in:
Ilya Kirillov
2020-03-23 12:03:56 +03:00
parent 3cd55b7827
commit 0ab91821c8
6 changed files with 93 additions and 103 deletions
@@ -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, Any?>): String {
val templatePath = template.templateId
val templateText = Template::class.java.getResource(templatePath).readText()
return FileTemplateUtil.mergeTemplate(data, templateText, false)
}
}
@@ -15,7 +15,8 @@ object IdeaServices {
IdeaFileSystemWizardService(),
IdeaBuildSystemAvailabilityWizardService(),
IdeaKotlinVersionProviderService(),
IdeaSettingSavingWizardService()
IdeaSettingSavingWizardService(),
IdeaVelocityEngineTemplateService()
)
fun createScopeDependent(project: Project) = listOfNotNull(
@@ -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, Any?>): String
fun Writer.writeTemplate(template: FileTemplate): TaskResult<Unit> {
val formatter = service<FileFormattingService>()
val text = renderTemplate(template.descriptor, template.data).let { text ->
formatter.formatFile(text, template.descriptor.relativePath.fileName.toString())
}
return service<FileSystemWizardService>().createFile(template.rootPath / template.descriptor.relativePath, text)
}
}
class VelocityTemplateEngineServiceImpl : TemplateEngineService, IdeaIndependentWizardService {
override fun renderTemplate(template: FileTemplateDescriptor, data: Map<String, Any?>): 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
}
}
@@ -12,7 +12,8 @@ object Services {
DummyFileFormattingService(),
KotlinVersionProviderServiceImpl(),
RunConfigurationsServiceImpl(),
SettingSavingWizardServiceImpl()
SettingSavingWizardServiceImpl(),
VelocityTemplateEngineServiceImpl()
)
}
@@ -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<TemplateEngineService>()
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<TemplateEngineService>()
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<InterceptionPoint<Any>, Any>
): TaskResult<Unit> {
val template = module.template ?: return UNIT_SUCCESS
@@ -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, Any?>): String
fun Writer.writeTemplate(template: FileTemplate): TaskResult<Unit> {
val formatter = service<FileFormattingService>()
val text = renderTemplate(template.descriptor, template.data).let { text ->
formatter.formatFile(text, template.descriptor.relativePath.fileName.toString())
}
return service<FileSystemWizardService>().createFile(template.rootPath / template.descriptor.relativePath, text)
}
}
class VelocityTemplateEngine : TemplateEngine {
override fun renderTemplate(template: FileTemplateDescriptor, data: Map<String, Any?>): 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<String, Any?>): List<FileTemplate> {
// val rootUri = VelocityTemplateEngine::class.java.getResource(path.toString()).toURI()
// return getFileSystem(rootUri).use { fileSystem ->
// val rootPath = fileSystem.rootDirectories.firstOrNull() ?: return@use emptyList<FileTemplate>()
// 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<out Any>.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<String, Any>())
// }
//}