Skip to content

Commit 1d532ed

Browse files
committed
fix: node tree resolve problem
1 parent c977b48 commit 1d532ed

File tree

7 files changed

+123
-69
lines changed

7 files changed

+123
-69
lines changed

src/com/dengzii/plugin/template/FileWriteCommand.kt

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,9 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
5656
fileTreeNode.expandPath()
5757
fileTreeNode.expandPkgName(true)
5858

59-
val failedList = mutableListOf<FileTreeNode>()
60-
fileTreeNode.children.forEach {
61-
failedList.addAll(createFileTree(context, it, current))
62-
}
59+
val failedList = createFileTree(context, fileTreeNode, current)
6360
if (failedList.isNotEmpty()) {
64-
val msg = failedList.joinToString("\n") { it.getRealName() }
61+
val msg = failedList.joinToString("\n") { it.name }
6562
NotificationUtils.showError(msg, "The following files creation failed.")
6663
}
6764
}
@@ -71,14 +68,19 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
7168
treeNode: FileTreeNode,
7269
currentDirectory: VirtualFile
7370
): List<FileTreeNode> {
71+
if (treeNode.isRoot()) {
72+
return treeNode.children.map {
73+
createFileTree(context, it, currentDirectory)
74+
}.flatten()
75+
}
7476
Logger.d(TAG, "create node $treeNode")
7577
val failedList = mutableListOf<FileTreeNode>()
7678
if (treeNode.isDir) {
7779
Logger.d(TAG, "create dir ${treeNode.getPath()}")
78-
val dir = kit.createDir(treeNode.getRealName(context), currentDirectory)
80+
val dir = kit.createDir(treeNode.name, currentDirectory)
7981
if (dir == null) {
8082
failedList.add(treeNode)
81-
Logger.e(TAG, "create directory failure: ${treeNode.getRealName(context)}")
83+
Logger.e(TAG, "create directory failure: ${treeNode.name}")
8284
} else {
8385
treeNode.children.forEach {
8486
failedList.addAll(createFileTree(context, it, dir))
@@ -87,23 +89,27 @@ class FileWriteCommand(private var kit: PluginKit, private var module: Module) :
8789
} else {
8890
val template = treeNode.getTemplateFile()
8991
if (template?.isNotBlank() == true) {
90-
val result = kit.createFileFromTemplate(
91-
treeNode.getRealName(context),
92-
template,
93-
treeNode.getPlaceholderInherit().orEmpty(),
94-
currentDirectory
95-
)
96-
if (result == null || !result.isValid) {
97-
failedList.add(treeNode)
98-
Logger.e(
99-
TAG,
100-
"create file from template failed, file: ${treeNode.getRealName(context)} template:$template"
92+
val result = try {
93+
kit.createFileFromTemplate(
94+
treeNode.name,
95+
template,
96+
treeNode.getPlaceholderInherit().orEmpty(),
97+
currentDirectory
10198
)
99+
} catch (e: Throwable) {
100+
e
101+
}
102+
if (result is Throwable) {
103+
NotificationUtils.showError(
104+
"file: ${treeNode.name} template:$template, error: ${result.message}",
105+
"Create file failed."
106+
)
107+
failedList.add(treeNode)
102108
} else {
103-
Logger.d(TAG, "create file from template ${treeNode.getRealName(context)}")
109+
Logger.d(TAG, "create file from template ${treeNode.name}")
104110
}
105111
} else {
106-
if (!kit.createFile(treeNode.getRealName(context), currentDirectory)) {
112+
if (!kit.createFile(treeNode.name, currentDirectory)) {
107113
failedList.add(treeNode)
108114
}
109115
Logger.d(TAG, "create file ${treeNode.getPath()}")

src/com/dengzii/plugin/template/model/FileTreeNode.kt

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ open class FileTreeNode() {
5353
@Transient
5454
var context: VelocityContext? = null
5555

56+
// flag whether the node is resolved, if true, represents the node info has been resolved via the velocity engine or placeholders.
57+
@Transient
58+
var resolved: Boolean = false
59+
5660
companion object {
5761

5862
private val TAG = FileTreeNode::class.java.simpleName
@@ -156,11 +160,11 @@ open class FileTreeNode() {
156160
fileName: String = this.name,
157161
): String {
158162
return if (isDir) {
159-
val rn = replacePlaceholder(velocityContext, fileName, getPlaceholderInherit(), false)
163+
val rn = getResolveTemplate(velocityContext, fileName, getPlaceholderInherit(), false)
160164
if (getModuleInherit()?.lowercaseDir == true) rn.lowercase() else rn
161165
} else {
162166
val capitalize = getModuleInherit()?.capitalizeFile ?: false
163-
replacePlaceholder(velocityContext, fileName, getPlaceholderInherit(), capitalize)
167+
getResolveTemplate(velocityContext, fileName, getPlaceholderInherit(), capitalize)
164168
}
165169
}
166170

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

184188
/**
185189
* Return all file template in tree node
190+
*
191+
* TODO: optimize
186192
*/
187193
fun getAllTemplateMap(): Map<String, String> {
188194
val templates = fileTemplates.orEmpty().toMutableMap()
@@ -212,19 +218,15 @@ open class FileTreeNode() {
212218
}
213219

214220
fun getFileTemplateInherit(): MutableMap<String, String>? {
215-
return if (fileTemplates.isNullOrEmpty()) {
216-
return parent?.getFileTemplateInherit()
217-
} else {
218-
fileTemplates
219-
}
221+
return parent?.getFileTemplateInherit()?.apply {
222+
putAll(fileTemplates.orEmpty())
223+
} ?: fileTemplates ?: mutableMapOf()
220224
}
221225

222226
fun getPlaceholderInherit(): MutableMap<String, String>? {
223-
return if (placeholders.isNullOrEmpty()) {
224-
return parent?.getPlaceholderInherit()
225-
} else {
226-
placeholders
227-
}
227+
return parent?.getPlaceholderInherit()?.apply {
228+
putAll(placeholders.orEmpty())
229+
} ?: placeholders ?: mutableMapOf()
228230
}
229231

230232
/**
@@ -243,20 +245,31 @@ open class FileTreeNode() {
243245
* Resolve all file template file name in tree node.
244246
*/
245247
fun resolveFileTemplate(context: VelocityContext? = getContextInherit()) {
246-
val templates = getAllTemplateMap()
247-
val placeholders = getPlaceholderInherit() ?: return
248-
if (fileTemplates != null && templates.isNotEmpty()) {
249-
templates.forEach { (key, value) ->
250-
val realName = getRealNameInternal(context, key)
251-
val realValue = replacePlaceholder(context, value, placeholders, false)
252-
fileTemplates!![realName] = realValue
248+
val templates = getFileTemplateInherit()
249+
if (templates != null) {
250+
val resolved = mutableMapOf<String, String>()
251+
val capitalize = getModuleInherit()?.capitalizeFile ?: false
252+
templates.forEach {
253+
val resolvedFileName =
254+
getResolveTemplate(context, it.key, getPlaceholderInherit(), capitalize = capitalize)
255+
resolved[resolvedFileName] = it.value
253256
}
257+
fileTemplates = resolved
254258
}
255259
traversal({ it, _ ->
256260
it.resolveFileTemplate(context)
257261
})
258262
}
259263

264+
fun resolve() {
265+
resolved = true
266+
resolveTreeFileName()
267+
resolveFileTemplate()
268+
traversal({ it, _ ->
269+
it.resolved = true
270+
})
271+
}
272+
260273
/**
261274
* Return the most matching file template.
262275
* If the node has template, return it, otherwise return the template in parent node.
@@ -608,23 +621,23 @@ open class FileTreeNode() {
608621
return result
609622
}
610623

611-
private fun replacePlaceholder(
624+
private fun getResolveTemplate(
612625
velocityContext: VelocityContext? = null,
613-
origin: String,
614-
placeholders: Map<String, String>?,
626+
template: String,
627+
variables: Map<String, String>?,
615628
capitalize: Boolean = false
616629
): String {
617630
if (velocityContext != null) {
618631
val writer = StringWriter()
619-
Velocity.evaluate(velocityContext, writer, "FileTreeNode", origin)
632+
Velocity.evaluate(velocityContext, writer, "FileTreeNode", template)
620633
return writer.toString()
621634
}
622635

623-
var after = origin
624-
if (placeholders.isNullOrEmpty()) {
625-
return origin
636+
var after = template
637+
if (variables.isNullOrEmpty()) {
638+
return template
626639
}
627-
placeholders.forEach { (k, v) ->
640+
variables.forEach { (k, v) ->
628641
var replacement = v
629642
if (capitalize) {
630643
replacement = v.lowercase(Locale.getDefault())
@@ -634,10 +647,10 @@ open class FileTreeNode() {
634647
}
635648
after = after.replace("\${$k}", replacement)
636649
}
637-
return if (after == origin || !after.contains('$')) {
650+
return if (after == template || !after.contains('$')) {
638651
after
639652
} else {
640-
replacePlaceholder(velocityContext, after, placeholders, capitalize)
653+
getResolveTemplate(velocityContext, after, variables, capitalize)
641654
}
642655
}
643656
}

src/com/dengzii/plugin/template/ui/CreateModuleDialog.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ private void onNextClick(ActionEvent e) {
7575
selectedModule.getTemplate().setPlaceholders(tablePlaceholder.getPairResult());
7676
selectedModule.getTemplate().setFileTemplates(tableFileTemplate.getPairResult());
7777

78-
previewPanel.setReplacePlaceholder(true);
78+
previewPanel.setPreviewMode(true);
7979
previewPanel.setModuleConfig(selectedModule);
8080

8181
if (currentPanelIndex == panels.size() - 1) {
@@ -135,7 +135,7 @@ private void onModuleConfigChange() {
135135
c.setEnabled(false);
136136
}
137137

138-
previewPanel.setReplacePlaceholder(true);
138+
previewPanel.setPreviewMode(true);
139139
previewPanel.setModuleConfig(selectedModule);
140140
tablePlaceholder.setPairData(selectedModule.getTemplate().getAllPlaceholdersMap());
141141
tableFileTemplate.setPairData(selectedModule.getTemplate().getAllTemplateMap());

src/com/dengzii/plugin/template/ui/PreviewPanel.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ class PreviewPanel(preview: Boolean) : JPanel() {
7979
initPanel()
8080
}
8181

82-
fun setReplacePlaceholder(replace: Boolean) {
83-
if (replace != replacePlaceholder) {
84-
replacePlaceholder = replace
82+
fun setPreviewMode(preview: Boolean) {
83+
if (preview != replacePlaceholder) {
84+
replacePlaceholder = preview
8585
showPlaceholder.isSelected = !replacePlaceholder
8686
fileTree.updateUI()
8787
}

src/com/dengzii/plugin/template/ui/RealConfigurePanel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ class RealConfigurePanel : ConfigurePanel() {
109109
currentConfig?.template?.removeAllPlaceHolderInTree()
110110
currentConfig?.template?.placeholders = tablePlaceholder.getPairResult()
111111
}
112-
panelPreview.setReplacePlaceholder(cbPlaceholder.isSelected)
112+
panelPreview.setPreviewMode(cbPlaceholder.isSelected)
113113
panelPreview.setOnTreeUpdateListener {
114114
modified = true
115115
}
116116
cbPlaceholder.addChangeListener {
117-
panelPreview.setReplacePlaceholder(cbPlaceholder.isSelected)
117+
panelPreview.setPreviewMode(cbPlaceholder.isSelected)
118118
}
119119
cbLowercaseDir.addChangeListener {
120120
currentConfig?.lowercaseDir = cbLowercaseDir.isSelected

src/com/dengzii/plugin/template/utils/PluginKit.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.intellij.psi.PsiElement
1515
import com.intellij.psi.PsiFile
1616
import com.intellij.psi.PsiManager
1717
import java.util.*
18+
import kotlin.jvm.Throws
1819

1920
/**
2021
* <pre>
@@ -107,25 +108,25 @@ class PluginKit private constructor(e: AnActionEvent) {
107108
return FileTemplateUtil.calculateAttributes(templateContent, Properties(), true, project)
108109
}
109110

111+
@Throws(Throwable::class)
110112
fun createFileFromTemplate(
111113
fileName: String,
112114
templateName: String,
113115
propertiesMap: Map<String, String>,
114116
directory: VirtualFile
115-
): PsiElement? {
117+
): PsiElement {
116118

117119
val fileTemplateManager = FileTemplateManager.getInstance(project)
118120
val properties = Properties(fileTemplateManager.defaultProperties)
119121
propertiesMap.forEach { (t, u) ->
120122
properties.setProperty(t.trim(), u)
121123
}
122-
val template = fileTemplateManager.getTemplate(templateName) ?: return null
123-
val psiDirectory = getPsiDirectoryByVirtualFile(directory) ?: return null
124+
val template = fileTemplateManager.getTemplate(templateName) ?: throw IllegalArgumentException("template not found.")
125+
val psiDirectory = getPsiDirectoryByVirtualFile(directory) ?: throw IllegalArgumentException("directory not found.")
124126
return try {
125127
FileTemplateUtil.createFromTemplate(template, fileName, properties, psiDirectory)
126128
} catch (e: Throwable) {
127-
e.printStackTrace()
128-
null
129+
throw e
129130
}
130131
}
131132

test/com/dengzii/plugin/template/model/FileTreeNodeTest.kt

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.dengzii.plugin.template.model
22

3+
import com.dengzii.plugin.template.Config
34
import junit.framework.TestCase
45
import org.apache.velocity.VelocityContext
56
import org.apache.velocity.util.StringUtils
@@ -85,35 +86,68 @@ class FileTreeNodeTest : TestCase() {
8586
println(m.template.getTreeGraph())
8687
}
8788

89+
90+
fun testAppcacheVelocity() {
91+
val r = """
92+
!{StringUtils.removeAndHump(!{FEATURE_NAME.replaceAll("[^\w]", "_")})}Module.kt
93+
""".replace("!", "\$")
94+
95+
val dsl = FileTreeDsl {
96+
placeholder("FT", "com-example")
97+
file("\${StringUtils.removeAndHump(\${FT.replaceAll(\"[_-]\", \"_\")})}")
98+
file(r)
99+
file("\${FT.replaceAll(\"[-]\", \"_\")}")
100+
}
101+
val module = Config.GSON.fromJson("", Module::class.java)
102+
103+
val m = Module.create(dsl, "test")
104+
m.enableApacheVelocity = true
105+
m.template.context = VelocityContext().apply {
106+
put("StringUtils", StringUtils::class.java)
107+
put("FT", "com-example")
108+
}
109+
m.template.resolve()
110+
println(m.template.getTreeGraph())
111+
}
112+
88113
fun testExpandPkg() {
89114

90115
val dsl = FileTreeDsl {
91116
placeholder("FT", "com_demo")
117+
fileTemplate("\${FT.replaceAll(\"[_]\", \".\")}.java", "Example")
118+
fileTemplate("\${StringUtils.removeAndHump(\${FT.replaceAll(\"[_]\", \"-\")})}Module.kt", "ExampleModule")
92119
dir("root") {
93-
dir("\${FT.replaceAll(\"[^\\w]\", \".\")}") {
94-
file("a.txt")
95-
}
96120
dir("\${FT.replaceAll(\"[_]\", \".\")}") {
97121
file("a.txt")
98122
}
99-
file("\${FT}.txt")
123+
file("\${FT.replaceAll(\"[_]\", \".\")}.java")
124+
file("\${StringUtils.removeAndHump(\${FT.replaceAll(\"[_]\", \"-\")})}Module.kt")
100125
}
101126
}
127+
102128
val m = Module.create(dsl, "test")
103129
m.packageNameToDir = true
104130
m.packageNameToDir = true
105131
m.enableApacheVelocity = true
106132

107133
m.template.context = VelocityContext().apply {
108-
put("StringUtils", StringUtils::class.java).apply {
109-
put("FT", "com_demo")
134+
put("StringUtils", StringUtils::class.java)
135+
m.template.getPlaceholderInherit()?.forEach { (k, v) ->
136+
put(k, v)
110137
}
111138
}
112139

113140
m.template.resolveTreeFileName()
114-
println(m.template.getTreeGraph())
141+
m.template.resolveFileTemplate()
142+
m.template.resolve()
143+
144+
m.template.children.last().children.last().let {
145+
println(it.name)
146+
println(it.fileTemplates)
147+
println(it.getTemplateFile())
148+
}
115149

116150
m.template.expandPkgName(true)
117-
println(m.template.getTreeGraph())
151+
println(m.template.getTreeGraph(templateFile = true))
118152
}
119153
}

0 commit comments

Comments
 (0)