Skip to content

Commit b15de24

Browse files
committed
Refactor SQL formatting logic to normalize indentation and reapply original formatting
1 parent 5df32fa commit b15de24

File tree

1 file changed

+43
-16
lines changed

1 file changed

+43
-16
lines changed

src/main/kotlin/org/domaframework/doma/intellij/formatter/visitor/DaoInjectionSqlVisitor.kt

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,36 +49,32 @@ class DaoInjectionSqlVisitor(
4949
val injected: PsiFile? = InjectionSqlUtil.initInjectionElement(element, project, expression)
5050
if (injected != null) {
5151
// Format SQL and store the task
52-
val formattedSql = formatInjectedSql(injected)
52+
val originalSqlText = injected.text
53+
val normalizedSql = normalizeIndentation(originalSqlText)
54+
val formattedSql = formatAsTemporarySqlFile(normalizedSql)
55+
val finalSql = reapplyOriginalIndentation(formattedSql, originalSqlText)
56+
5357
val originalText = expression.value?.toString() ?: return
54-
if (formattedSql != originalText) {
55-
formattingTasks.add(FormattingTask(expression, formattedSql))
58+
if (finalSql != originalText) {
59+
formattingTasks.add(FormattingTask(expression, finalSql))
5660
}
5761
}
5862
}
5963

60-
fun processAll() {
64+
fun processAll(removeSpace: (String, Boolean) -> String) {
6165
if (formattingTasks.isEmpty()) return
6266

6367
// Apply all formatting tasks in a single write action
6468
WriteCommandAction.runWriteCommandAction(project, "Format Injected SQL", null, {
6569
// Sort by text range in descending order to maintain offsets
6670
formattingTasks.sortedByDescending { it.expression.textRange.startOffset }.forEach { task ->
6771
if (task.expression.isValid) {
68-
replaceHostStringLiteral(task.expression, task.formattedText)
72+
replaceHostStringLiteral(task.expression, task.formattedText, removeSpace)
6973
}
7074
}
7175
})
7276
}
7377

74-
private fun formatInjectedSql(injectedFile: PsiFile): String =
75-
try {
76-
val originalSqlText = injectedFile.text
77-
formatAsTemporarySqlFile(originalSqlText)
78-
} catch (_: Exception) {
79-
injectedFile.text
80-
}
81-
8278
/**
8379
* Execute formatting as a temporary SQL file
8480
*/
@@ -107,16 +103,18 @@ class DaoInjectionSqlVisitor(
107103
private fun replaceHostStringLiteral(
108104
literalExpression: PsiLiteralExpression,
109105
formattedSqlText: String,
106+
removeSpace: (String, Boolean) -> String,
110107
) {
111108
try {
112-
// Create new string literal
113-
val newLiteralText = createFormattedLiteralText(formattedSqlText)
109+
val normalizedSql = normalizeIndentation(formattedSqlText)
110+
val newLiteralText = createFormattedLiteralText(normalizedSql)
111+
val removeSpaceText = removeSpace(newLiteralText, false)
114112

115113
// Replace PSI element
116114
val elementFactory =
117115
com.intellij.psi.JavaPsiFacade
118116
.getElementFactory(project)
119-
val newLiteral = elementFactory.createExpressionFromText(newLiteralText, literalExpression)
117+
val newLiteral = elementFactory.createExpressionFromText(removeSpaceText, literalExpression)
120118
val manager = PsiDocumentManager.getInstance(literalExpression.project)
121119
val document = manager.getDocument(literalExpression.containingFile) ?: return
122120
document.replaceString(literalExpression.textRange.startOffset, literalExpression.textRange.endOffset, newLiteral.text)
@@ -125,11 +123,40 @@ class DaoInjectionSqlVisitor(
125123
}
126124
}
127125

126+
private fun normalizeIndentation(sqlText: String): String {
127+
val lines = sqlText.lines()
128+
val minIndent =
129+
lines
130+
.filter { it.isNotBlank() }
131+
.minOfOrNull { it.indexOfFirst { char -> !char.isWhitespace() } } ?: 0
132+
133+
return lines.joinToString(StringUtil.LINE_SEPARATE) { line ->
134+
if (line.isBlank()) line else line.drop(minIndent)
135+
}
136+
}
137+
128138
/**
129139
* Create appropriate Java string literal from formatted SQL
130140
*/
131141
private fun createFormattedLiteralText(formattedSqlText: String): String {
132142
val lines = formattedSqlText.split(StringUtil.LINE_SEPARATE)
133143
return "\"\"\"${StringUtil.LINE_SEPARATE}${lines.joinToString(StringUtil.LINE_SEPARATE)}\"\"\""
134144
}
145+
146+
private fun reapplyOriginalIndentation(
147+
formattedSql: String,
148+
originalSql: String,
149+
): String {
150+
val originalLines = originalSql.lines()
151+
val formattedLines = formattedSql.lines()
152+
153+
val originalIndent =
154+
originalLines
155+
.firstOrNull { it.isNotBlank() }
156+
?.takeWhile { it.isWhitespace() } ?: ""
157+
158+
return formattedLines.joinToString(StringUtil.LINE_SEPARATE) { line ->
159+
if (line.isBlank()) line else originalIndent + line
160+
}
161+
}
135162
}

0 commit comments

Comments
 (0)