Skip to content

Commit 48c9db9

Browse files
committed
Refactor line-breaking logic in the processor:
Add all necessary line breaks for relevant elements, and control whether to retain those line breaks within the block processing logic.
1 parent 34b2e5f commit 48c9db9

File tree

2 files changed

+67
-124
lines changed

2 files changed

+67
-124
lines changed

src/main/kotlin/org/domaframework/doma/intellij/formatter/processor/SqlFormatPreProcessor.kt

Lines changed: 62 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import com.intellij.psi.PsiFile
2424
import com.intellij.psi.PsiWhiteSpace
2525
import com.intellij.psi.TokenType
2626
import com.intellij.psi.impl.source.codeStyle.PreFormatProcessor
27+
import com.intellij.psi.util.PsiTreeUtil
2728
import com.intellij.psi.util.elementType
28-
import com.intellij.psi.util.prevLeafs
2929
import org.domaframework.doma.intellij.common.util.PluginLoggerUtil
3030
import org.domaframework.doma.intellij.formatter.util.CreateQueryType
3131
import org.domaframework.doma.intellij.formatter.util.SqlKeywordUtil
@@ -35,6 +35,19 @@ import org.domaframework.doma.intellij.setting.SqlLanguage
3535
import org.jetbrains.kotlin.psi.psiUtil.startOffset
3636

3737
class SqlFormatPreProcessor : PreFormatProcessor {
38+
private val targetElementTypes =
39+
listOf(
40+
SqlTypes.KEYWORD,
41+
SqlTypes.LEFT_PAREN,
42+
SqlTypes.RIGHT_PAREN,
43+
SqlTypes.BLOCK_COMMENT,
44+
SqlTypes.LINE_COMMENT,
45+
SqlTypes.WORD,
46+
SqlTypes.COMMA,
47+
SqlTypes.BLOCK_COMMENT,
48+
SqlTypes.OTHER,
49+
)
50+
3851
override fun process(
3952
node: ASTNode,
4053
rangeToReformat: TextRange,
@@ -71,17 +84,15 @@ class SqlFormatPreProcessor : PreFormatProcessor {
7184
when (it.elementType) {
7285
SqlTypes.KEYWORD -> {
7386
keywordIndex--
74-
newKeyword = getKeywordNewText(index, it, createQueryType, keywordList)
87+
newKeyword = getKeywordNewText(it)
7588
}
7689

7790
SqlTypes.LEFT_PAREN -> {
7891
newKeyword =
7992
if (createQueryType == CreateQueryType.TABLE) {
8093
getNewLineString(it.prevSibling, getUpperText(it))
8194
} else if (keywordIndex > 0) {
82-
if (replaceKeywordList[keywordIndex - 1].text.lowercase() == "insert" ||
83-
replaceKeywordList[keywordIndex - 1].text.lowercase() == "into"
84-
) {
95+
if (listOf("insert", "into", "all").contains(replaceKeywordList[keywordIndex - 1].text.lowercase())) {
8596
getNewLineString(it.prevSibling, getUpperText(it))
8697
} else {
8798
getUpperText(it)
@@ -93,12 +104,7 @@ class SqlFormatPreProcessor : PreFormatProcessor {
93104

94105
SqlTypes.RIGHT_PAREN -> {
95106
newKeyword =
96-
getRightPatternNewText(
97-
it,
98-
newKeyword,
99-
replaceKeywordList[keywordIndex - 1],
100-
createQueryType,
101-
)
107+
getRightPatternNewText(it)
102108
}
103109

104110
SqlTypes.WORD -> {
@@ -112,40 +118,7 @@ class SqlFormatPreProcessor : PreFormatProcessor {
112118
document.deleteString(textRangeStart, textRangeEnd)
113119
document.insertString(textRangeStart, newKeyword)
114120
} else {
115-
// Remove spaces after newlines to reset indentation
116-
val nextSibling = it.nextSibling
117-
if (nextSibling.elementType == SqlTypes.BLOCK_COMMENT) {
118-
removeSpacesAroundNewline(document, it.textRange)
119-
} else if (keywordIndex < replaceKeywordList.size) {
120-
val nextElement = replaceKeywordList[keywordIndex]
121-
if (isNewLineOnlyCreateTable(nextSibling) && createQueryType == CreateQueryType.TABLE) {
122-
removeSpacesAroundNewline(document, it.textRange)
123-
} else if (isSubGroupFirstElement(nextElement)) {
124-
document.deleteString(textRangeStart, textRangeEnd)
125-
} else if (isCreateViewAs(replaceKeywordList[keywordIndex], createQueryType)) {
126-
removeSpacesAroundNewline(document, it.textRange)
127-
} else {
128-
val isNewLineGroup =
129-
SqlKeywordUtil.Companion.getIndentType(nextElement.text ?: "").isNewLineGroup()
130-
val isSetLineKeyword =
131-
if (keywordIndex > 0) {
132-
SqlKeywordUtil.Companion.isSetLineKeyword(
133-
nextElement.text,
134-
replaceKeywordList[keywordIndex - 1].text,
135-
)
136-
} else {
137-
false
138-
}
139-
140-
if (isNewLineGroup && !isSetLineKeyword || keywordList[index].elementType == SqlTypes.COMMA) {
141-
removeSpacesAroundNewline(document, it.textRange)
142-
} else {
143-
document.replaceString(textRangeStart, textRangeEnd, " ")
144-
}
145-
}
146-
} else {
147-
removeSpacesAroundNewline(document, it.textRange)
148-
}
121+
removeSpacesAroundNewline(document, it as PsiWhiteSpace)
149122
}
150123
}
151124

@@ -156,68 +129,62 @@ class SqlFormatPreProcessor : PreFormatProcessor {
156129

157130
private fun removeSpacesAroundNewline(
158131
document: Document,
159-
range: TextRange,
132+
element: PsiWhiteSpace,
160133
) {
134+
val singleSpace = " "
135+
val newLine = "\n"
136+
val range = element.textRange
161137
val originalText = document.getText(range)
162-
val newText = originalText.replace(Regex("\\s*\\n\\s*"), "\n")
138+
val nextElement = element.nextSibling
139+
val nextElementText = nextElement?.let { document.getText(it.textRange) } ?: ""
140+
141+
var newText = ""
142+
if (!targetElementTypes.contains(nextElement?.elementType)) {
143+
newText = originalText.replace(originalText, singleSpace)
144+
} else {
145+
newText =
146+
when (nextElement.elementType) {
147+
SqlTypes.LINE_COMMENT -> {
148+
if (nextElementText.startsWith(newLine)) {
149+
originalText.replace(originalText, singleSpace)
150+
} else if (originalText.contains(newLine)) {
151+
originalText.replace(Regex("\\s*\\n\\s*"), newLine)
152+
} else {
153+
originalText.replace(originalText, singleSpace)
154+
}
155+
}
156+
157+
else -> {
158+
if (nextElementText.contains(newLine) == true) {
159+
originalText.replace(originalText, singleSpace)
160+
} else if (originalText.contains(newLine)) {
161+
originalText.replace(Regex("\\s*\\n\\s*"), newLine)
162+
} else {
163+
originalText.replace(originalText, newLine)
164+
}
165+
}
166+
}
167+
}
163168
document.replaceString(range.startOffset, range.endOffset, newText)
164169
}
165170

166171
/**
167172
* Checks for special case keyword elements and specific combinations of keywords with line breaks and capitalization only
168173
*/
169-
private fun getKeywordNewText(
170-
index: Int,
171-
element: PsiElement,
172-
createQueryType: CreateQueryType,
173-
keywordList: List<PsiElement>,
174-
): String =
175-
if (element.text.lowercase() == "end") {
176-
getNewLineString(element.prevSibling, getUpperText(element))
177-
} else if (isCreateViewAs(element, createQueryType)) {
178-
getNewLineString(element.prevSibling, getUpperText(element))
179-
} else if (isSubGroupFirstElement(element)) {
180-
getUpperText(element)
181-
} else if (SqlKeywordUtil.Companion.getIndentType(element.text).isNewLineGroup()) {
182-
if (index > 0 &&
183-
SqlKeywordUtil.Companion.isSetLineKeyword(
184-
element.text,
185-
keywordList[index - 1].text,
186-
)
187-
) {
188-
getUpperText(element)
189-
} else {
190-
getNewLineString(element.prevSibling, getUpperText(element))
191-
}
174+
private fun getKeywordNewText(element: PsiElement): String {
175+
val keywordText = element.text.lowercase()
176+
val upperText = getUpperText(element)
177+
return if (SqlKeywordUtil.getIndentType(keywordText).isNewLineGroup()) {
178+
val prevElement = PsiTreeUtil.prevLeaf(element)
179+
getNewLineString(prevElement, upperText)
192180
} else {
193-
getUpperText(element)
181+
upperText
194182
}
183+
}
195184

196-
private fun getRightPatternNewText(
197-
element: PsiElement,
198-
keyword: String,
199-
nextKeyword: PsiElement,
200-
createQueryType: CreateQueryType,
201-
): String {
202-
var newKeyword = keyword
185+
private fun getRightPatternNewText(element: PsiElement): String {
203186
val elementText = element.text
204-
if (createQueryType == CreateQueryType.TABLE) {
205-
val prefixElements =
206-
getElementsBeforeKeyword(element.prevLeafs.toList()) { it.elementType == SqlTypes.LEFT_PAREN }
207-
val containsColumnRaw =
208-
prefixElements.findLast { isColumnDefinedRawElementType(it) } != null
209-
newKeyword =
210-
if (containsColumnRaw) {
211-
getNewLineString(element.prevSibling, elementText)
212-
} else {
213-
elementText
214-
}
215-
} else if (nextKeyword.text.lowercase() == "set") {
216-
newKeyword = getNewLineString(element.prevSibling, elementText)
217-
} else {
218-
newKeyword = elementText
219-
}
220-
return newKeyword
187+
return getNewLineString(element.prevSibling, elementText)
221188
}
222189

223190
private fun getWordNewText(
@@ -248,18 +215,6 @@ class SqlFormatPreProcessor : PreFormatProcessor {
248215
}
249216
}
250217

251-
private fun isCreateViewAs(
252-
element: PsiElement,
253-
createQueryType: CreateQueryType,
254-
): Boolean =
255-
element.text.lowercase() == "as" &&
256-
createQueryType == CreateQueryType.VIEW
257-
258-
private fun isColumnDefinedRawElementType(element: PsiElement): Boolean =
259-
element.elementType == SqlTypes.WORD ||
260-
element.elementType == SqlTypes.KEYWORD ||
261-
element.elementType == SqlTypes.COMMA
262-
263218
private fun getCreateQueryGroup(
264219
keywordList: List<PsiElement>,
265220
index: Int,
@@ -286,19 +241,6 @@ class SqlFormatPreProcessor : PreFormatProcessor {
286241
return attachmentKeywordType
287242
}
288243

289-
/**
290-
* The column definition elements of Create Table, "(", "WORD", and ")" must be line breaks
291-
*/
292-
private fun isNewLineOnlyCreateTable(nextElement: PsiElement): Boolean =
293-
nextElement.elementType == SqlTypes.LEFT_PAREN ||
294-
nextElement.elementType == SqlTypes.RIGHT_PAREN ||
295-
nextElement.elementType == SqlTypes.WORD
296-
297-
fun <T> getElementsBeforeKeyword(
298-
elements: List<T>,
299-
isLeft: (T) -> Boolean,
300-
): List<T> = elements.takeWhile { element -> !isLeft(element) }
301-
302244
private fun getNewLineString(
303245
prevElement: PsiElement?,
304246
text: String,
@@ -316,10 +258,6 @@ class SqlFormatPreProcessor : PreFormatProcessor {
316258
element.text
317259
}
318260

319-
private fun isSubGroupFirstElement(element: PsiElement): Boolean =
320-
getElementsBeforeKeyword(element.prevLeafs.toList()) { it.elementType == SqlTypes.LEFT_PAREN }
321-
.findLast { it !is PsiWhiteSpace } == null
322-
323261
private fun logging() {
324262
PluginLoggerUtil.Companion.countLogging(
325263
this::class.java.simpleName,

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ class SqlFormatVisitor : PsiRecursiveElementVisitor() {
6666

6767
override fun visitWhiteSpace(space: PsiWhiteSpace) {
6868
super.visitWhiteSpace(space)
69+
if (PsiTreeUtil.getParentOfType(space, SqlBlockComment::class.java) == null) {
70+
replaces.add(space)
71+
}
72+
return
73+
6974
val nextElement = space.nextSibling
7075
if (nextElement != null &&
7176
(

0 commit comments

Comments
 (0)