Skip to content

Commit a99ae2c

Browse files
authored
Merge pull request #86 from domaframework/fix/formatter-indent
Fix/formatter indent
2 parents bbe3094 + 4b54ca0 commit a99ae2c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1258
-321
lines changed

src/main/kotlin/org/domaframework/doma/intellij/extension/expr/SqlElExtensions.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,15 @@ package org.domaframework.doma.intellij.extension.expr
1818
import com.intellij.psi.PsiElement
1919
import com.intellij.psi.util.PsiTreeUtil
2020
import com.intellij.psi.util.elementType
21+
import org.domaframework.doma.intellij.psi.SqlCustomElCommentExpr
2122
import org.domaframework.doma.intellij.psi.SqlElClass
23+
import org.domaframework.doma.intellij.psi.SqlElElseifDirective
24+
import org.domaframework.doma.intellij.psi.SqlElForDirective
25+
import org.domaframework.doma.intellij.psi.SqlElIfDirective
2226
import org.domaframework.doma.intellij.psi.SqlElPrimaryExpr
2327
import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr
2428
import org.domaframework.doma.intellij.psi.SqlTypes
29+
import kotlin.invoke
2530

2631
val SqlElStaticFieldAccessExpr.accessElements: List<PsiElement>
2732
get() {
@@ -43,3 +48,13 @@ val SqlElStaticFieldAccessExpr.fqdn: String
4348
val fqdn = PsiTreeUtil.getChildrenOfTypeAsList(elClazz, PsiElement::class.java)
4449
return fqdn.toList().joinToString("") { it.text }
4550
}
51+
52+
fun SqlCustomElCommentExpr.isConditionOrLoopDirective(): Boolean =
53+
PsiTreeUtil.getChildOfType(this, SqlElIfDirective::class.java) != null ||
54+
PsiTreeUtil.getChildOfType(this, SqlElForDirective::class.java) != null ||
55+
PsiTreeUtil.getChildOfType(
56+
this,
57+
SqlElElseifDirective::class.java,
58+
) != null ||
59+
this.findElementAt(2)?.elementType == SqlTypes.EL_END ||
60+
this.findElementAt(2)?.elementType == SqlTypes.EL_ELSE

src/main/kotlin/org/domaframework/doma/intellij/formatter/SqlBlockBuilder.kt

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
package org.domaframework.doma.intellij.formatter
1717

1818
import org.domaframework.doma.intellij.formatter.block.SqlBlock
19-
import org.domaframework.doma.intellij.formatter.block.group.SqlSubGroupBlock
19+
import org.domaframework.doma.intellij.formatter.block.expr.SqlElBlockCommentBlock
20+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock
2021

2122
open class SqlBlockBuilder {
2223
private val groupTopNodeIndexHistory = mutableListOf<Pair<Int, SqlBlock>>()
@@ -25,6 +26,8 @@ open class SqlBlockBuilder {
2526

2627
fun getGroupTopNodeIndexHistory(): List<Pair<Int, SqlBlock>> = groupTopNodeIndexHistory
2728

29+
fun getLastGroup(): SqlBlock? = groupTopNodeIndexHistory.lastOrNull()?.second
30+
2831
fun addGroupTopNodeIndexHistory(block: Pair<Int, SqlBlock>) {
2932
groupTopNodeIndexHistory.add(block)
3033
}
@@ -37,19 +40,21 @@ open class SqlBlockBuilder {
3740
if (commentBlocks.isNotEmpty()) {
3841
var index = 0
3942
commentBlocks.forEach { block ->
40-
val indentLen =
41-
if (index == 0 &&
42-
baseIndent.parentBlock is SqlSubGroupBlock &&
43-
baseIndent.parentBlock?.childBlocks?.size == 1
44-
) {
45-
1
46-
} else {
47-
baseIndent.indent.indentLen
48-
}
49-
block.indent.indentLevel = IndentType.NONE
50-
block.indent.indentLen = indentLen
51-
block.indent.groupIndentLen = 0
52-
index++
43+
if (block !is SqlElBlockCommentBlock) {
44+
val indentLen =
45+
if (index == 0 &&
46+
baseIndent.parentBlock is SqlSubGroupBlock &&
47+
baseIndent.parentBlock?.childBlocks?.size == 1
48+
) {
49+
1
50+
} else {
51+
baseIndent.indent.indentLen
52+
}
53+
block.indent.indentLevel = IndentType.NONE
54+
block.indent.indentLen = indentLen
55+
block.indent.groupIndentLen = 0
56+
index++
57+
}
5358
}
5459
commentBlocks.clear()
5560
}
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
/*
2+
* Copyright Doma Tools Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.domaframework.doma.intellij.formatter
17+
18+
import com.intellij.lang.ASTNode
19+
import com.intellij.psi.PsiComment
20+
import com.intellij.psi.util.PsiTreeUtil
21+
import org.domaframework.doma.intellij.extension.expr.isConditionOrLoopDirective
22+
import org.domaframework.doma.intellij.formatter.block.SqlBlock
23+
import org.domaframework.doma.intellij.formatter.block.SqlBlockCommentBlock
24+
import org.domaframework.doma.intellij.formatter.block.SqlColumnBlock
25+
import org.domaframework.doma.intellij.formatter.block.SqlCommaBlock
26+
import org.domaframework.doma.intellij.formatter.block.SqlCommentBlock
27+
import org.domaframework.doma.intellij.formatter.block.SqlKeywordBlock
28+
import org.domaframework.doma.intellij.formatter.block.SqlTableBlock
29+
import org.domaframework.doma.intellij.formatter.block.SqlWordBlock
30+
import org.domaframework.doma.intellij.formatter.block.expr.SqlElBlockCommentBlock
31+
import org.domaframework.doma.intellij.formatter.block.expr.SqlElConditionLoopCommentBlock
32+
import org.domaframework.doma.intellij.formatter.block.group.SqlColumnDefinitionRawGroupBlock
33+
import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlCreateKeywordGroupBlock
34+
import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInlineGroupBlock
35+
import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInlineSecondGroupBlock
36+
import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInsertKeywordGroupBlock
37+
import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlJoinGroupBlock
38+
import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock
39+
import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlUpdateKeywordGroupBlock
40+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlColumnDefinitionGroupBlock
41+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlColumnGroupBlock
42+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlDataTypeParamBlock
43+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlFunctionParamBlock
44+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlInsertColumnGroupBlock
45+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlParallelListBlock
46+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubQueryGroupBlock
47+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlUpdateColumnGroupBlock
48+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlUpdateValueGroupBlock
49+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlViewGroupBlock
50+
import org.domaframework.doma.intellij.psi.SqlCustomElCommentExpr
51+
import org.domaframework.doma.intellij.psi.SqlTypes
52+
53+
class SqlBlockUtil(
54+
private val sqlBlock: SqlBlock,
55+
) {
56+
val wrap = sqlBlock.wrap
57+
val alignment = sqlBlock.alignment
58+
val spacingBuilder = sqlBlock.spacingBuilder
59+
60+
fun getKeywordBlock(
61+
child: ASTNode,
62+
lastGroupBlock: SqlBlock?,
63+
): SqlBlock {
64+
// Because we haven't yet set the parent-child relationship of the block,
65+
// the parent group references groupTopNodeIndexHistory.
66+
val indentLevel = SqlKeywordUtil.getIndentType(child.text)
67+
val keywordText = child.text.lowercase()
68+
if (indentLevel.isNewLineGroup()) {
69+
when (indentLevel) {
70+
IndentType.JOIN -> {
71+
return if (SqlKeywordUtil.isJoinKeyword(child.text)) {
72+
SqlJoinGroupBlock(child, wrap, alignment, spacingBuilder)
73+
} else if (lastGroupBlock is SqlJoinGroupBlock) {
74+
SqlKeywordBlock(child, IndentType.ATTACHED, wrap, alignment, spacingBuilder)
75+
} else {
76+
SqlJoinGroupBlock(child, wrap, alignment, spacingBuilder)
77+
}
78+
}
79+
80+
IndentType.INLINE_SECOND -> {
81+
return SqlInlineSecondGroupBlock(child, wrap, alignment, spacingBuilder)
82+
}
83+
84+
IndentType.TOP -> {
85+
if (keywordText == "create") {
86+
return SqlCreateKeywordGroupBlock(child, wrap, alignment, spacingBuilder)
87+
}
88+
if (keywordText == "insert") {
89+
return SqlInsertKeywordGroupBlock(child, wrap, alignment, spacingBuilder)
90+
}
91+
92+
return SqlKeywordGroupBlock(child, indentLevel, wrap, alignment, spacingBuilder)
93+
}
94+
95+
IndentType.SECOND -> {
96+
return if (keywordText == "set") {
97+
SqlUpdateKeywordGroupBlock(child, wrap, alignment, spacingBuilder)
98+
} else {
99+
SqlKeywordGroupBlock(child, indentLevel, wrap, alignment, spacingBuilder)
100+
}
101+
}
102+
103+
else -> {
104+
return SqlKeywordGroupBlock(child, indentLevel, wrap, alignment, spacingBuilder)
105+
}
106+
}
107+
}
108+
109+
when (indentLevel) {
110+
IndentType.INLINE -> {
111+
if (!SqlKeywordUtil.isSetLineKeyword(
112+
child.text,
113+
lastGroupBlock?.node?.text ?: "",
114+
)
115+
) {
116+
return SqlInlineGroupBlock(child, wrap, alignment, spacingBuilder)
117+
}
118+
}
119+
120+
IndentType.ATTACHED -> {
121+
if (lastGroupBlock is SqlCreateKeywordGroupBlock) {
122+
lastGroupBlock.setCreateQueryType(child.text)
123+
return SqlKeywordBlock(child, indentLevel, wrap, alignment, spacingBuilder)
124+
}
125+
}
126+
127+
IndentType.OPTIONS -> {
128+
if (child.text.lowercase() == "as") {
129+
val parentCreateBlock =
130+
lastGroupBlock as? SqlCreateKeywordGroupBlock
131+
?: lastGroupBlock?.parentBlock as? SqlCreateKeywordGroupBlock
132+
if (parentCreateBlock != null && parentCreateBlock.createType == CreateQueryType.VIEW) {
133+
return SqlViewGroupBlock(child, wrap, alignment, spacingBuilder)
134+
}
135+
}
136+
}
137+
138+
else -> return SqlKeywordBlock(child, indentLevel, wrap, alignment, spacingBuilder)
139+
}
140+
return SqlKeywordBlock(child, indentLevel, wrap, alignment, spacingBuilder)
141+
}
142+
143+
fun getSubGroupBlock(
144+
lastGroup: SqlBlock?,
145+
child: ASTNode,
146+
): SqlBlock {
147+
if (child.treePrev.elementType == SqlTypes.WORD) {
148+
return SqlFunctionParamBlock(child, wrap, alignment, spacingBuilder)
149+
}
150+
151+
when (lastGroup) {
152+
is SqlKeywordGroupBlock -> {
153+
val lastKeyword =
154+
lastGroup.childBlocks
155+
.lastOrNull { SqlKeywordUtil.isOptionSqlKeyword(it.node.text) }
156+
if (lastKeyword != null && lastKeyword.node.text.lowercase() == "in") {
157+
return SqlParallelListBlock(child, wrap, alignment, spacingBuilder)
158+
}
159+
if (lastGroup is SqlCreateKeywordGroupBlock) {
160+
return SqlColumnDefinitionGroupBlock(child, wrap, alignment, spacingBuilder)
161+
}
162+
if (lastGroup is SqlInsertKeywordGroupBlock) {
163+
return SqlInsertColumnGroupBlock(child, wrap, alignment, spacingBuilder)
164+
}
165+
if (lastGroup is SqlUpdateKeywordGroupBlock) {
166+
return if (lastGroup.childBlocks.firstOrNull { it is SqlUpdateColumnGroupBlock } == null) {
167+
SqlUpdateColumnGroupBlock(child, wrap, alignment, spacingBuilder)
168+
} else if (lastGroup.childBlocks.lastOrNull { it is SqlUpdateColumnGroupBlock } != null) {
169+
SqlUpdateValueGroupBlock(child, wrap, alignment, spacingBuilder)
170+
} else {
171+
SqlSubQueryGroupBlock(child, wrap, alignment, spacingBuilder)
172+
}
173+
}
174+
return SqlSubQueryGroupBlock(child, wrap, alignment, spacingBuilder)
175+
}
176+
177+
is SqlColumnDefinitionRawGroupBlock ->
178+
return SqlDataTypeParamBlock(child, wrap, alignment, spacingBuilder)
179+
180+
else ->
181+
return SqlSubQueryGroupBlock(child, wrap, alignment, spacingBuilder)
182+
}
183+
}
184+
185+
fun getCommaGroupBlock(
186+
lastGroup: SqlBlock?,
187+
child: ASTNode,
188+
): SqlBlock =
189+
when (lastGroup) {
190+
is SqlColumnDefinitionGroupBlock, is SqlColumnDefinitionRawGroupBlock ->
191+
SqlColumnDefinitionRawGroupBlock(
192+
child,
193+
wrap,
194+
alignment,
195+
spacingBuilder,
196+
)
197+
198+
is SqlColumnGroupBlock, is SqlKeywordGroupBlock -> {
199+
if (lastGroup.indent.indentLevel == IndentType.SECOND) {
200+
SqlCommaBlock(child, wrap, alignment, spacingBuilder)
201+
} else {
202+
SqlColumnGroupBlock(child, wrap, alignment, spacingBuilder)
203+
}
204+
}
205+
206+
else -> SqlCommaBlock(child, wrap, alignment, spacingBuilder)
207+
}
208+
209+
fun getWordBlock(
210+
lastGroup: SqlBlock?,
211+
child: ASTNode,
212+
): SqlBlock =
213+
when (lastGroup) {
214+
is SqlKeywordGroupBlock -> {
215+
when {
216+
SqlKeywordUtil.isBeforeTableKeyword(lastGroup.node.text) ->
217+
SqlTableBlock(
218+
child,
219+
wrap,
220+
alignment,
221+
spacingBuilder,
222+
)
223+
224+
else -> SqlWordBlock(child, wrap, alignment, spacingBuilder)
225+
}
226+
}
227+
228+
is SqlColumnDefinitionGroupBlock -> {
229+
lastGroup.alignmentColumnName = child.text
230+
SqlColumnDefinitionRawGroupBlock(
231+
child,
232+
wrap,
233+
alignment,
234+
spacingBuilder,
235+
)
236+
}
237+
238+
is SqlColumnDefinitionRawGroupBlock -> {
239+
if (lastGroup.childBlocks.isEmpty()) {
240+
lastGroup.columnName = child.text
241+
SqlColumnBlock(
242+
child,
243+
wrap,
244+
alignment,
245+
spacingBuilder,
246+
)
247+
} else {
248+
SqlWordBlock(child, wrap, alignment, spacingBuilder)
249+
}
250+
}
251+
252+
else -> SqlWordBlock(child, wrap, alignment, spacingBuilder)
253+
}
254+
255+
fun getBlockCommentBlock(
256+
child: ASTNode,
257+
blockCommentSpacingBuilder: SqlCustomSpacingBuilder?,
258+
): SqlCommentBlock {
259+
if (PsiTreeUtil.getChildOfType(child.psi, PsiComment::class.java) != null) {
260+
return SqlBlockCommentBlock(
261+
child,
262+
wrap,
263+
alignment,
264+
spacingBuilder,
265+
)
266+
}
267+
if (child.psi is SqlCustomElCommentExpr &&
268+
(child.psi as SqlCustomElCommentExpr).isConditionOrLoopDirective()
269+
) {
270+
return SqlElConditionLoopCommentBlock(
271+
child,
272+
wrap,
273+
alignment,
274+
blockCommentSpacingBuilder,
275+
spacingBuilder,
276+
)
277+
}
278+
return SqlElBlockCommentBlock(
279+
child,
280+
wrap,
281+
alignment,
282+
blockCommentSpacingBuilder,
283+
spacingBuilder,
284+
)
285+
}
286+
}

0 commit comments

Comments
 (0)