Skip to content

Commit ab94184

Browse files
authored
Merge pull request #441 from domaframework/fix/sql-format-case-in-function
Improve SQL CASE Statement Formatting
2 parents 7b2c80d + 3457127 commit ab94184

25 files changed

+463
-299
lines changed

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ open class SqlBlock(
105105
protected fun isConditionLoopDirectiveRegisteredBeforeParent(): Boolean {
106106
val firstPrevBlock = (prevBlocks.lastOrNull() as? SqlElConditionLoopCommentBlock)
107107
parentBlock?.let { parent ->
108-
109108
return (childBlocks.firstOrNull() as? SqlElConditionLoopCommentBlock)?.isBeforeParentBlock() == true ||
110109
firstPrevBlock != null &&
111110
firstPrevBlock.conditionEnd != null &&
@@ -132,7 +131,7 @@ open class SqlBlock(
132131
protected fun isElementAfterConditionLoopDirective(): Boolean =
133132
(parentBlock as? SqlElConditionLoopCommentBlock)?.let { parent ->
134133
parent.childBlocks.firstOrNull() == this &&
135-
(parent.parentBlock is SqlNewGroupBlock || parent.parentBlock is SqlElConditionLoopCommentBlock)
134+
(parent.parentBlock is SqlNewGroupBlock || parent.isParentConditionLoopDirective())
136135
} == true
137136

138137
protected fun isElementAfterConditionLoopEnd(): Boolean {
@@ -160,6 +159,8 @@ open class SqlBlock(
160159
)?.conditionEnd
161160
)
162161

162+
fun isParentConditionLoopDirective(): Boolean = parentBlock is SqlElConditionLoopCommentBlock
163+
163164
protected fun isFirstChildConditionLoopDirective(): Boolean = childBlocks.firstOrNull() is SqlElConditionLoopCommentBlock
164165

165166
fun getChildBlocksDropLast(

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlFileBlock.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,6 @@ open class SqlFileBlock(
359359
}
360360

361361
is SqlInlineGroupBlock -> {
362-
// case-end
363362
blockRelationBuilder.updateGroupBlockParentAndAddGroup(
364363
childBlock,
365364
)
@@ -471,7 +470,7 @@ open class SqlFileBlock(
471470
return SqlCustomSpacingBuilder().getSpacing(childBlock2)
472471
}
473472

474-
if (childBlock1 is SqlWhitespaceBlock && childBlock2.parentBlock is SqlElConditionLoopCommentBlock) {
473+
if (childBlock1 is SqlWhitespaceBlock && childBlock2.isParentConditionLoopDirective()) {
475474
val child1 = childBlock2.parentBlock as SqlElConditionLoopCommentBlock
476475
SqlCustomSpacingBuilder()
477476
.getSpacingElDirectiveComment(child1, childBlock2)

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlKeywordBlock.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ package org.domaframework.doma.intellij.formatter.block
1717

1818
import com.intellij.lang.ASTNode
1919
import com.intellij.psi.formatter.common.AbstractBlock
20-
import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock
2120
import org.domaframework.doma.intellij.formatter.block.conflict.SqlDoGroupBlock
2221
import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock
2322
import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock
@@ -96,7 +95,7 @@ open class SqlKeywordBlock(
9695
}
9796

9897
else -> {
99-
if (parentBlock is SqlElConditionLoopCommentBlock) {
98+
if (isParentConditionLoopDirective()) {
10099
parentBlock?.indent?.groupIndentLen ?: 1
101100
} else {
102101
parentBlock?.indent?.groupIndentLen?.plus(1) ?: 1

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlLiteralBlock.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,18 @@ open class SqlLiteralBlock(
4141
override fun setParentGroupBlock(lastGroup: SqlBlock?) {
4242
super.setParentGroupBlock(lastGroup)
4343
indent.indentLevel = IndentType.NONE
44-
indent.indentLen = 0
45-
indent.groupIndentLen = 0
44+
indent.indentLen = createBlockIndentLen()
45+
indent.groupIndentLen = createGroupIndentLen()
4646
}
4747

4848
override fun buildChildren(): MutableList<AbstractBlock> = mutableListOf()
4949

5050
override fun isLeaf(): Boolean = true
51+
52+
override fun createBlockIndentLen(): Int =
53+
if (isFirstChildConditionLoopDirective() || isParentConditionLoopDirective()) {
54+
parentBlock?.indent?.indentLen ?: 0
55+
} else {
56+
0
57+
}
5158
}

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlArrayCommaBlock.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.formatter.block.comma
1818
import com.intellij.lang.ASTNode
1919
import com.intellij.psi.formatter.common.AbstractBlock
2020
import org.domaframework.doma.intellij.formatter.block.SqlBlock
21-
import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock
2221
import org.domaframework.doma.intellij.formatter.util.IndentType
2322
import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext
2423

@@ -49,5 +48,5 @@ class SqlArrayCommaBlock(
4948

5049
override fun createGroupIndentLen(): Int = indent.indentLen.plus(1)
5150

52-
override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = parentBlock is SqlElConditionLoopCommentBlock
51+
override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = isParentConditionLoopDirective()
5352
}

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlBlockCommentBlock.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ import com.intellij.lang.ASTNode
2121
import com.intellij.psi.formatter.common.AbstractBlock
2222
import org.domaframework.doma.intellij.formatter.block.SqlBlock
2323
import org.domaframework.doma.intellij.formatter.block.SqlUnknownBlock
24+
import org.domaframework.doma.intellij.formatter.block.expr.SqlElSymbolBlock
2425
import org.domaframework.doma.intellij.formatter.builder.SqlCustomSpacingBuilder
2526
import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext
2627
import org.domaframework.doma.intellij.psi.SqlTypes
2728

2829
open class SqlBlockCommentBlock(
2930
node: ASTNode,
30-
private val customSpacingBuilder: SqlCustomSpacingBuilder,
3131
private val context: SqlBlockFormattingContext,
3232
) : SqlDefaultCommentBlock(
3333
node,
@@ -41,16 +41,15 @@ open class SqlBlockCommentBlock(
4141
SqlTypes.BLOCK_COMMENT_START -> SqlCommentStartBlock(child, context)
4242
SqlTypes.BLOCK_COMMENT_END -> SqlCommentEndBlock(child, context)
4343
SqlTypes.BLOCK_COMMENT_CONTENT -> SqlCommentContentBlock(child, context)
44+
SqlTypes.EL_PARSER_LEVEL_COMMENT -> SqlElSymbolBlock(child, context)
4445
else -> SqlUnknownBlock(child, context)
4546
}
4647
}
4748

48-
override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = hasLineBreakBefore()
49+
override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = true
4950

5051
override fun getSpacing(
5152
child1: Block?,
5253
child2: Block,
53-
): Spacing? =
54-
customSpacingBuilder.getCustomSpacing(child1, child2)
55-
?: SqlCustomSpacingBuilder.normalSpacing
54+
): Spacing? = SqlCustomSpacingBuilder.nonSpacing
5655
}

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElBlockCommentBlock.kt

Lines changed: 50 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package org.domaframework.doma.intellij.formatter.block.comment
1818
import com.intellij.formatting.Block
1919
import com.intellij.formatting.Spacing
2020
import com.intellij.lang.ASTNode
21+
import com.intellij.psi.PsiElement
2122
import com.intellij.psi.formatter.common.AbstractBlock
2223
import com.intellij.psi.util.PsiTreeUtil
2324
import com.intellij.psi.util.elementType
@@ -55,32 +56,25 @@ open class SqlElBlockCommentBlock(
5556
val directiveType: SqlElCommentDirectiveType = initDirectiveType()
5657

5758
private fun initDirectiveType(): SqlElCommentDirectiveType {
58-
val element = this.node.psi
59+
val element = node.psi
5960
val contentElement = PsiTreeUtil.firstChild(element).nextSibling
6061

61-
if (contentElement is SqlElIfDirective ||
62+
return when {
63+
isConditionOrLoopDirective(contentElement) -> SqlElCommentDirectiveType.CONDITION_LOOP
64+
contentElement.elementType == SqlTypes.HASH -> SqlElCommentDirectiveType.EMBEDDED
65+
contentElement.elementType == SqlTypes.EL_EXPAND -> SqlElCommentDirectiveType.EXPAND
66+
contentElement.elementType == SqlTypes.EL_POPULATE -> SqlElCommentDirectiveType.POPULATE
67+
contentElement.elementType == SqlTypes.CARET -> SqlElCommentDirectiveType.LITERAL
68+
else -> SqlElCommentDirectiveType.NORMAL
69+
}
70+
}
71+
72+
private fun isConditionOrLoopDirective(contentElement: PsiElement?): Boolean =
73+
contentElement is SqlElIfDirective ||
6274
contentElement is SqlElForDirective ||
6375
contentElement is SqlElElseifDirective ||
6476
contentElement.elementType == SqlTypes.EL_ELSE ||
6577
contentElement.elementType == SqlTypes.EL_END
66-
) {
67-
return SqlElCommentDirectiveType.CONDITION_LOOP
68-
}
69-
if (contentElement.elementType == SqlTypes.HASH) {
70-
return SqlElCommentDirectiveType.EMBEDDED
71-
}
72-
if (contentElement.elementType == SqlTypes.EL_EXPAND) {
73-
return SqlElCommentDirectiveType.EXPAND
74-
}
75-
if (contentElement.elementType == SqlTypes.EL_POPULATE) {
76-
return SqlElCommentDirectiveType.POPULATE
77-
}
78-
if (contentElement.elementType == SqlTypes.CARET) {
79-
return SqlElCommentDirectiveType.LITERAL
80-
}
81-
82-
return SqlElCommentDirectiveType.NORMAL
83-
}
8478

8579
override fun buildChildren(): MutableList<AbstractBlock> = buildChildBlocks { getBlock(it) }
8680

@@ -91,103 +85,67 @@ open class SqlElBlockCommentBlock(
9185
->
9286
SqlOperationBlock(child, context)
9387

94-
SqlTypes.EL_EQ_EXPR, SqlTypes.EL_NE_EXPR, SqlTypes.EL_GE_EXPR, SqlTypes.EL_GT_EXPR, SqlTypes.EL_LE_EXPR, SqlTypes.EL_LT_EXPR,
95-
SqlTypes.EL_AND_EXPR, SqlTypes.EL_OR_EXPR, SqlTypes.EL_NOT_EXPR,
96-
SqlTypes.EL_ADD_EXPR, SqlTypes.EL_SUBTRACT_EXPR, SqlTypes.EL_MULTIPLY_EXPR, SqlTypes.EL_DIVIDE_EXPR, SqlTypes.EL_MOD_EXPR,
88+
SqlTypes.EL_EQ_EXPR, SqlTypes.EL_NE_EXPR, SqlTypes.EL_GE_EXPR, SqlTypes.EL_GT_EXPR,
89+
SqlTypes.EL_LE_EXPR, SqlTypes.EL_LT_EXPR, SqlTypes.EL_AND_EXPR, SqlTypes.EL_OR_EXPR,
90+
SqlTypes.EL_NOT_EXPR, SqlTypes.EL_ADD_EXPR, SqlTypes.EL_SUBTRACT_EXPR,
91+
SqlTypes.EL_MULTIPLY_EXPR, SqlTypes.EL_DIVIDE_EXPR, SqlTypes.EL_MOD_EXPR,
9792
->
98-
SqlElBlockCommentBlock(
99-
child,
100-
context,
101-
createBlockDirectiveCommentSpacingBuilder(),
102-
)
103-
104-
SqlTypes.EL_FIELD_ACCESS_EXPR ->
105-
SqlElFieldAccessBlock(
106-
child,
107-
context,
108-
)
93+
SqlElBlockCommentBlock(child, context, createBlockDirectiveCommentSpacingBuilder())
10994

95+
SqlTypes.EL_FIELD_ACCESS_EXPR -> SqlElFieldAccessBlock(child, context)
11096
SqlTypes.BLOCK_COMMENT_START -> SqlCommentStartBlock(child, context)
111-
11297
SqlTypes.BLOCK_COMMENT_END -> SqlCommentEndBlock(child, context)
113-
114-
SqlTypes.EL_STATIC_FIELD_ACCESS_EXPR ->
115-
SqlElStaticFieldAccessBlock(
116-
child,
117-
context,
118-
)
119-
120-
SqlTypes.EL_FUNCTION_CALL_EXPR ->
121-
SqlElFunctionCallBlock(
122-
child,
123-
context,
124-
)
125-
126-
SqlTypes.BLOCK_COMMENT_CONTENT ->
127-
SqlBlockCommentBlock(child, createBlockCommentSpacingBuilder(), context)
128-
98+
SqlTypes.EL_STATIC_FIELD_ACCESS_EXPR -> SqlElStaticFieldAccessBlock(child, context)
99+
SqlTypes.EL_FUNCTION_CALL_EXPR -> SqlElFunctionCallBlock(child, context)
100+
SqlTypes.BLOCK_COMMENT_CONTENT -> SqlBlockCommentBlock(child, context)
129101
else -> SqlUnknownBlock(child, context)
130102
}
131103

132-
protected fun createBlockCommentSpacingBuilder(): SqlCustomSpacingBuilder =
133-
SqlCustomSpacingBuilder()
134-
.withSpacing(
135-
SqlTypes.BLOCK_COMMENT_START,
136-
SqlTypes.BLOCK_COMMENT_CONTENT,
137-
Spacing.createSpacing(1, 1, 0, false, 0),
138-
)
104+
protected fun createBlockCommentSpacingBuilder(): SqlCustomSpacingBuilder {
105+
val noSpacing = Spacing.createSpacing(0, 0, 0, false, 0)
106+
val singleSpace = Spacing.createSpacing(1, 1, 0, false, 0)
107+
108+
return SqlCustomSpacingBuilder()
109+
.withSpacing(SqlTypes.BLOCK_COMMENT_START, SqlTypes.BLOCK_COMMENT_CONTENT, singleSpace)
110+
.withSpacing(SqlTypes.BLOCK_COMMENT_START, SqlTypes.EL_PARSER_LEVEL_COMMENT, noSpacing)
111+
.withSpacing(SqlTypes.EL_PARSER_LEVEL_COMMENT, SqlTypes.BLOCK_COMMENT_CONTENT, noSpacing)
112+
}
139113

140114
override fun createBlockDirectiveCommentSpacingBuilder(): SqlCustomSpacingBuilder = createBlockCommentSpacingBuilder()
141115

142116
override fun getSpacing(
143117
child1: Block?,
144118
child2: Block,
145119
): Spacing? =
146-
customSpacingBuilder?.getCustomSpacing(child1, child2) ?: spacingBuilder.getSpacing(
147-
this,
148-
child1,
149-
child2,
150-
)
120+
customSpacingBuilder?.getCustomSpacing(child1, child2)
121+
?: spacingBuilder.getSpacing(this, child1, child2)
151122

152123
override fun isLeaf(): Boolean = false
153124

154-
override fun createBlockIndentLen(): Int {
125+
override fun createBlockIndentLen(): Int =
155126
parentBlock?.let { parent ->
156-
return when (parent) {
127+
when (parent) {
157128
is SqlElConditionLoopCommentBlock -> parent.indent.groupIndentLen
158-
is SqlSubQueryGroupBlock -> {
159-
if (parent.getChildBlocksDropLast().isEmpty()) {
160-
if (isConditionLoopDirectiveRegisteredBeforeParent()) {
161-
parent.indent.groupIndentLen
162-
} else {
163-
parent.indent.groupIndentLen
164-
}
165-
} else if (parent.isFirstLineComment) {
166-
parent.indent.groupIndentLen.minus(2)
167-
} else {
168-
parent.indent.groupIndentLen
169-
}
170-
}
129+
is SqlSubQueryGroupBlock -> calculateSubQueryIndent(parent)
171130
is SqlValuesGroupBlock -> parent.indent.indentLen
172-
is SqlKeywordGroupBlock -> parent.indent.groupIndentLen.plus(1)
131+
is SqlKeywordGroupBlock -> parent.indent.groupIndentLen + 1
173132
else -> parent.indent.groupIndentLen
174133
}
134+
} ?: 0
135+
136+
private fun calculateSubQueryIndent(parent: SqlSubQueryGroupBlock): Int =
137+
when {
138+
parent.getChildBlocksDropLast().isEmpty() -> parent.indent.groupIndentLen
139+
parent.isFirstLineComment -> parent.indent.groupIndentLen - 2
140+
else -> parent.indent.groupIndentLen
175141
}
176-
return 0
177-
}
178142

179143
override fun isSaveSpace(lastGroup: SqlBlock?): Boolean =
180144
parentBlock?.let { parent ->
181-
isConditionLoopDirectiveRegisteredBeforeParent() ||
182-
(
183-
(
184-
parent is SqlWithQuerySubGroupBlock ||
185-
parent is SqlValuesGroupBlock ||
186-
parent is SqlElConditionLoopCommentBlock
187-
) &&
188-
parent.childBlocks
189-
.dropLast(1)
190-
.none { it !is SqlElConditionLoopCommentBlock }
191-
)
145+
isConditionLoopDirectiveRegisteredBeforeParent() || isParentWithOnlyConditionLoopBlocks(parent)
192146
} == true
147+
148+
private fun isParentWithOnlyConditionLoopBlocks(parent: SqlBlock): Boolean =
149+
(parent is SqlWithQuerySubGroupBlock || parent is SqlValuesGroupBlock || parent is SqlElConditionLoopCommentBlock) &&
150+
parent.childBlocks.dropLast(1).none { it !is SqlElConditionLoopCommentBlock }
193151
}

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlKeywordGroupBlock.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ open class SqlKeywordGroupBlock(
182182

183183
override fun isSaveSpace(lastGroup: SqlBlock?): Boolean {
184184
val conditionLastGroup =
185-
if (parentBlock is SqlElConditionLoopCommentBlock) {
185+
if (isParentConditionLoopDirective()) {
186186
parentBlock?.parentBlock
187187
} else {
188188
lastGroup

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/condition/SqlConditionKeywordGroupBlock.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import com.intellij.lang.ASTNode
1919
import org.domaframework.doma.intellij.formatter.block.SqlBlock
2020
import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock
2121
import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateKeywordGroupBlock
22+
import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineSecondGroupBlock
2223
import org.domaframework.doma.intellij.formatter.block.group.keyword.option.SqlSecondOptionKeywordGroupBlock
2324
import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlWhereGroupBlock
2425
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock
@@ -56,6 +57,7 @@ class SqlConditionKeywordGroupBlock(
5657
return when (parent) {
5758
is SqlElConditionLoopCommentBlock -> parent.indent.groupIndentLen
5859
is SqlSubGroupBlock -> calculateSubGroupIndent(groupLen)
60+
is SqlInlineSecondGroupBlock -> calculateInlineSecondIndent(groupLen)
5961
else -> parent.indent.groupIndentLen - getNodeText().length
6062
}
6163
}
@@ -67,6 +69,13 @@ class SqlConditionKeywordGroupBlock(
6769
groupLen + 1
6870
}
6971

72+
private fun calculateInlineSecondIndent(groupLen: Int): Int =
73+
if (getNodeText() == "and") {
74+
groupLen.plus(1)
75+
} else {
76+
groupLen.plus(2)
77+
}
78+
7079
override fun createGroupIndentLen(): Int {
7180
parentBlock?.let { parent ->
7281
if (parent is SqlWhereGroupBlock) {

src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineGroupBlock.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.inline
1818
import com.intellij.lang.ASTNode
1919
import com.intellij.psi.formatter.common.AbstractBlock
2020
import org.domaframework.doma.intellij.formatter.block.SqlBlock
21-
import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock
2221
import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock
22+
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock
2323
import org.domaframework.doma.intellij.formatter.util.IndentType
2424
import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext
2525

@@ -50,12 +50,21 @@ open class SqlInlineGroupBlock(
5050

5151
override fun createBlockIndentLen(): Int =
5252
parentBlock?.let { parent ->
53-
if (parent is SqlElConditionLoopCommentBlock) {
53+
if (isParentConditionLoopDirective() || isFirstChildConditionLoopDirective() ||
54+
parent is SqlSubGroupBlock
55+
) {
5456
parent.indent.groupIndentLen
5557
} else {
5658
parent.indent.groupIndentLen.plus(1)
5759
}
5860
} ?: 1
5961

6062
override fun createGroupIndentLen(): Int = indent.indentLen.plus(getNodeText().length)
63+
64+
override fun isSaveSpace(lastGroup: SqlBlock?): Boolean {
65+
if (lastGroup is SqlInlineSecondGroupBlock) {
66+
return true
67+
}
68+
return super.isSaveSpace(lastGroup)
69+
}
6170
}

0 commit comments

Comments
 (0)