Skip to content

Commit

Permalink
fix: node tree resolve problem
Browse files Browse the repository at this point in the history
  • Loading branch information
dengzii committed Feb 26, 2024
1 parent c977b48 commit 1d532ed
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 69 deletions.
46 changes: 26 additions & 20 deletions src/com/dengzii/plugin/template/FileWriteCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,9 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
fileTreeNode.expandPath()
fileTreeNode.expandPkgName(true)

val failedList = mutableListOf<FileTreeNode>()
fileTreeNode.children.forEach {
failedList.addAll(createFileTree(context, it, current))
}
val failedList = createFileTree(context, fileTreeNode, current)
if (failedList.isNotEmpty()) {
val msg = failedList.joinToString("\n") { it.getRealName() }
val msg = failedList.joinToString("\n") { it.name }
NotificationUtils.showError(msg, "The following files creation failed.")
}
}
Expand All @@ -71,14 +68,19 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
treeNode: FileTreeNode,
currentDirectory: VirtualFile
): List<FileTreeNode> {
if (treeNode.isRoot()) {
return treeNode.children.map {
createFileTree(context, it, currentDirectory)
}.flatten()
}
Logger.d(TAG, "create node $treeNode")
val failedList = mutableListOf<FileTreeNode>()
if (treeNode.isDir) {
Logger.d(TAG, "create dir ${treeNode.getPath()}")
val dir = kit.createDir(treeNode.getRealName(context), currentDirectory)
val dir = kit.createDir(treeNode.name, currentDirectory)
if (dir == null) {
failedList.add(treeNode)
Logger.e(TAG, "create directory failure: ${treeNode.getRealName(context)}")
Logger.e(TAG, "create directory failure: ${treeNode.name}")
} else {
treeNode.children.forEach {
failedList.addAll(createFileTree(context, it, dir))
Expand All @@ -87,23 +89,27 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
} else {
val template = treeNode.getTemplateFile()
if (template?.isNotBlank() == true) {
val result = kit.createFileFromTemplate(
treeNode.getRealName(context),
template,
treeNode.getPlaceholderInherit().orEmpty(),
currentDirectory
)
if (result == null || !result.isValid) {
failedList.add(treeNode)
Logger.e(
TAG,
"create file from template failed, file: ${treeNode.getRealName(context)} template:$template"
val result = try {
kit.createFileFromTemplate(
treeNode.name,
template,
treeNode.getPlaceholderInherit().orEmpty(),
currentDirectory
)
} catch (e: Throwable) {
e
}
if (result is Throwable) {
NotificationUtils.showError(
"file: ${treeNode.name} template:$template, error: ${result.message}",
"Create file failed."
)
failedList.add(treeNode)
} else {
Logger.d(TAG, "create file from template ${treeNode.getRealName(context)}")
Logger.d(TAG, "create file from template ${treeNode.name}")
}
} else {
if (!kit.createFile(treeNode.getRealName(context), currentDirectory)) {
if (!kit.createFile(treeNode.name, currentDirectory)) {
failedList.add(treeNode)
}
Logger.d(TAG, "create file ${treeNode.getPath()}")
Expand Down
71 changes: 42 additions & 29 deletions src/com/dengzii/plugin/template/model/FileTreeNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ open class FileTreeNode() {
@Transient
var context: VelocityContext? = null

// flag whether the node is resolved, if true, represents the node info has been resolved via the velocity engine or placeholders.
@Transient
var resolved: Boolean = false

companion object {

private val TAG = FileTreeNode::class.java.simpleName
Expand Down Expand Up @@ -156,11 +160,11 @@ open class FileTreeNode() {
fileName: String = this.name,
): String {
return if (isDir) {
val rn = replacePlaceholder(velocityContext, fileName, getPlaceholderInherit(), false)
val rn = getResolveTemplate(velocityContext, fileName, getPlaceholderInherit(), false)
if (getModuleInherit()?.lowercaseDir == true) rn.lowercase() else rn
} else {
val capitalize = getModuleInherit()?.capitalizeFile ?: false
replacePlaceholder(velocityContext, fileName, getPlaceholderInherit(), capitalize)
getResolveTemplate(velocityContext, fileName, getPlaceholderInherit(), capitalize)
}
}

Expand All @@ -183,6 +187,8 @@ open class FileTreeNode() {

/**
* Return all file template in tree node
*
* TODO: optimize
*/
fun getAllTemplateMap(): Map<String, String> {
val templates = fileTemplates.orEmpty().toMutableMap()
Expand Down Expand Up @@ -212,19 +218,15 @@ open class FileTreeNode() {
}

fun getFileTemplateInherit(): MutableMap<String, String>? {
return if (fileTemplates.isNullOrEmpty()) {
return parent?.getFileTemplateInherit()
} else {
fileTemplates
}
return parent?.getFileTemplateInherit()?.apply {
putAll(fileTemplates.orEmpty())
} ?: fileTemplates ?: mutableMapOf()
}

fun getPlaceholderInherit(): MutableMap<String, String>? {
return if (placeholders.isNullOrEmpty()) {
return parent?.getPlaceholderInherit()
} else {
placeholders
}
return parent?.getPlaceholderInherit()?.apply {
putAll(placeholders.orEmpty())
} ?: placeholders ?: mutableMapOf()
}

/**
Expand All @@ -243,20 +245,31 @@ open class FileTreeNode() {
* Resolve all file template file name in tree node.
*/
fun resolveFileTemplate(context: VelocityContext? = getContextInherit()) {
val templates = getAllTemplateMap()
val placeholders = getPlaceholderInherit() ?: return
if (fileTemplates != null && templates.isNotEmpty()) {
templates.forEach { (key, value) ->
val realName = getRealNameInternal(context, key)
val realValue = replacePlaceholder(context, value, placeholders, false)
fileTemplates!![realName] = realValue
val templates = getFileTemplateInherit()
if (templates != null) {
val resolved = mutableMapOf<String, String>()
val capitalize = getModuleInherit()?.capitalizeFile ?: false
templates.forEach {
val resolvedFileName =
getResolveTemplate(context, it.key, getPlaceholderInherit(), capitalize = capitalize)
resolved[resolvedFileName] = it.value
}
fileTemplates = resolved
}
traversal({ it, _ ->
it.resolveFileTemplate(context)
})
}

fun resolve() {
resolved = true
resolveTreeFileName()
resolveFileTemplate()
traversal({ it, _ ->
it.resolved = true
})
}

/**
* Return the most matching file template.
* If the node has template, return it, otherwise return the template in parent node.
Expand Down Expand Up @@ -608,23 +621,23 @@ open class FileTreeNode() {
return result
}

private fun replacePlaceholder(
private fun getResolveTemplate(
velocityContext: VelocityContext? = null,
origin: String,
placeholders: Map<String, String>?,
template: String,
variables: Map<String, String>?,
capitalize: Boolean = false
): String {
if (velocityContext != null) {
val writer = StringWriter()
Velocity.evaluate(velocityContext, writer, "FileTreeNode", origin)
Velocity.evaluate(velocityContext, writer, "FileTreeNode", template)
return writer.toString()
}

var after = origin
if (placeholders.isNullOrEmpty()) {
return origin
var after = template
if (variables.isNullOrEmpty()) {
return template
}
placeholders.forEach { (k, v) ->
variables.forEach { (k, v) ->
var replacement = v
if (capitalize) {
replacement = v.lowercase(Locale.getDefault())
Expand All @@ -634,10 +647,10 @@ open class FileTreeNode() {
}
after = after.replace("\${$k}", replacement)
}
return if (after == origin || !after.contains('$')) {
return if (after == template || !after.contains('$')) {
after
} else {
replacePlaceholder(velocityContext, after, placeholders, capitalize)
getResolveTemplate(velocityContext, after, variables, capitalize)
}
}
}
4 changes: 2 additions & 2 deletions src/com/dengzii/plugin/template/ui/CreateModuleDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ private void onNextClick(ActionEvent e) {
selectedModule.getTemplate().setPlaceholders(tablePlaceholder.getPairResult());
selectedModule.getTemplate().setFileTemplates(tableFileTemplate.getPairResult());

previewPanel.setReplacePlaceholder(true);
previewPanel.setPreviewMode(true);
previewPanel.setModuleConfig(selectedModule);

if (currentPanelIndex == panels.size() - 1) {
Expand Down Expand Up @@ -135,7 +135,7 @@ private void onModuleConfigChange() {
c.setEnabled(false);
}

previewPanel.setReplacePlaceholder(true);
previewPanel.setPreviewMode(true);
previewPanel.setModuleConfig(selectedModule);
tablePlaceholder.setPairData(selectedModule.getTemplate().getAllPlaceholdersMap());
tableFileTemplate.setPairData(selectedModule.getTemplate().getAllTemplateMap());
Expand Down
6 changes: 3 additions & 3 deletions src/com/dengzii/plugin/template/ui/PreviewPanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ class PreviewPanel(preview: Boolean) : JPanel() {
initPanel()
}

fun setReplacePlaceholder(replace: Boolean) {
if (replace != replacePlaceholder) {
replacePlaceholder = replace
fun setPreviewMode(preview: Boolean) {
if (preview != replacePlaceholder) {
replacePlaceholder = preview
showPlaceholder.isSelected = !replacePlaceholder
fileTree.updateUI()
}
Expand Down
4 changes: 2 additions & 2 deletions src/com/dengzii/plugin/template/ui/RealConfigurePanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ class RealConfigurePanel : ConfigurePanel() {
currentConfig?.template?.removeAllPlaceHolderInTree()
currentConfig?.template?.placeholders = tablePlaceholder.getPairResult()
}
panelPreview.setReplacePlaceholder(cbPlaceholder.isSelected)
panelPreview.setPreviewMode(cbPlaceholder.isSelected)
panelPreview.setOnTreeUpdateListener {
modified = true
}
cbPlaceholder.addChangeListener {
panelPreview.setReplacePlaceholder(cbPlaceholder.isSelected)
panelPreview.setPreviewMode(cbPlaceholder.isSelected)
}
cbLowercaseDir.addChangeListener {
currentConfig?.lowercaseDir = cbLowercaseDir.isSelected
Expand Down
11 changes: 6 additions & 5 deletions src/com/dengzii/plugin/template/utils/PluginKit.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import java.util.*
import kotlin.jvm.Throws

/**
* <pre>
Expand Down Expand Up @@ -107,25 +108,25 @@ class PluginKit private constructor(e: AnActionEvent) {
return FileTemplateUtil.calculateAttributes(templateContent, Properties(), true, project)
}

@Throws(Throwable::class)
fun createFileFromTemplate(
fileName: String,
templateName: String,
propertiesMap: Map<String, String>,
directory: VirtualFile
): PsiElement? {
): PsiElement {

val fileTemplateManager = FileTemplateManager.getInstance(project)
val properties = Properties(fileTemplateManager.defaultProperties)
propertiesMap.forEach { (t, u) ->
properties.setProperty(t.trim(), u)
}
val template = fileTemplateManager.getTemplate(templateName) ?: return null
val psiDirectory = getPsiDirectoryByVirtualFile(directory) ?: return null
val template = fileTemplateManager.getTemplate(templateName) ?: throw IllegalArgumentException("template not found.")
val psiDirectory = getPsiDirectoryByVirtualFile(directory) ?: throw IllegalArgumentException("directory not found.")
return try {
FileTemplateUtil.createFromTemplate(template, fileName, properties, psiDirectory)
} catch (e: Throwable) {
e.printStackTrace()
null
throw e
}
}

Expand Down
50 changes: 42 additions & 8 deletions test/com/dengzii/plugin/template/model/FileTreeNodeTest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.dengzii.plugin.template.model

import com.dengzii.plugin.template.Config
import junit.framework.TestCase
import org.apache.velocity.VelocityContext
import org.apache.velocity.util.StringUtils
Expand Down Expand Up @@ -85,35 +86,68 @@ class FileTreeNodeTest : TestCase() {
println(m.template.getTreeGraph())
}


fun testAppcacheVelocity() {
val r = """
!{StringUtils.removeAndHump(!{FEATURE_NAME.replaceAll("[^\w]", "_")})}Module.kt
""".replace("!", "\$")

val dsl = FileTreeDsl {
placeholder("FT", "com-example")
file("\${StringUtils.removeAndHump(\${FT.replaceAll(\"[_-]\", \"_\")})}")
file(r)
file("\${FT.replaceAll(\"[-]\", \"_\")}")
}
val module = Config.GSON.fromJson("", Module::class.java)

val m = Module.create(dsl, "test")
m.enableApacheVelocity = true
m.template.context = VelocityContext().apply {
put("StringUtils", StringUtils::class.java)
put("FT", "com-example")
}
m.template.resolve()
println(m.template.getTreeGraph())
}

fun testExpandPkg() {

val dsl = FileTreeDsl {
placeholder("FT", "com_demo")
fileTemplate("\${FT.replaceAll(\"[_]\", \".\")}.java", "Example")
fileTemplate("\${StringUtils.removeAndHump(\${FT.replaceAll(\"[_]\", \"-\")})}Module.kt", "ExampleModule")
dir("root") {
dir("\${FT.replaceAll(\"[^\\w]\", \".\")}") {
file("a.txt")
}
dir("\${FT.replaceAll(\"[_]\", \".\")}") {
file("a.txt")
}
file("\${FT}.txt")
file("\${FT.replaceAll(\"[_]\", \".\")}.java")
file("\${StringUtils.removeAndHump(\${FT.replaceAll(\"[_]\", \"-\")})}Module.kt")
}
}

val m = Module.create(dsl, "test")
m.packageNameToDir = true
m.packageNameToDir = true
m.enableApacheVelocity = true

m.template.context = VelocityContext().apply {
put("StringUtils", StringUtils::class.java).apply {
put("FT", "com_demo")
put("StringUtils", StringUtils::class.java)
m.template.getPlaceholderInherit()?.forEach { (k, v) ->
put(k, v)
}
}

m.template.resolveTreeFileName()
println(m.template.getTreeGraph())
m.template.resolveFileTemplate()
m.template.resolve()

m.template.children.last().children.last().let {
println(it.name)
println(it.fileTemplates)
println(it.getTemplateFile())
}

m.template.expandPkgName(true)
println(m.template.getTreeGraph())
println(m.template.getTreeGraph(templateFile = true))
}
}

0 comments on commit 1d532ed

Please sign in to comment.