@@ -50,11 +50,13 @@ open class SqlBlock(
5050 var indentLevel : IndentType ,
5151 /* *
5252 * The number of indentation spaces for this element.
53+ *
5354 * Returns `0` if there is no line break.
5455 */
5556 var indentLen : Int ,
5657 /* *
5758 * Indentation baseline applied to the group itself.
59+ *
5860 * Even if the group does not start on a new line,
5961 * it determines and applies indentation to the group based on factors such as the number of preceding characters.
6062 */
@@ -81,6 +83,48 @@ open class SqlBlock(
8183
8284 private fun isExcludedFromTextLength (block : SqlBlock ): Boolean = block.node.elementType in setOf (SqlTypes .DOT , SqlTypes .RIGHT_PAREN )
8385
86+ /* *
87+ * Checks if a conditional loop directive is registered before the parent block.
88+ *
89+ * @note
90+ * If the next element after a conditional directive is not a conditional directive block,
91+ * the directive becomes a child of the next element block.
92+ * Therefore, if the first element in [childBlocks] is a conditional directive,
93+ * it can be determined that—syntactically—the conditional directive was placed immediately before the current block.
94+ */
95+ protected fun isConditionLoopDirectiveRegisteredBeforeParent (): Boolean {
96+ val firstPrevBlock = (prevBlocks.lastOrNull() as ? SqlElConditionLoopCommentBlock )
97+ parentBlock?.let { parent ->
98+ return firstPrevBlock != null &&
99+ firstPrevBlock.conditionEnd != null &&
100+ firstPrevBlock.node.startOffset > parent.node.startOffset
101+ }
102+ return false
103+ }
104+
105+ /* *
106+ * Determines if this is the element immediately after a conditional loop directive.
107+ *
108+ * @note
109+ * The parent conditional loop directive becomes a child of the element immediately after the conditional loop directive.
110+ * In the following case, "%if" is a child of "status", and the following "=" and "'pending'" are children of "%if".
111+ * Therefore, set the condition to break line only when the parent of the conditional loop directive is a group block.
112+ *
113+ * @example
114+ * ```sql
115+ * WHERE
116+ * /*%if status == "pending" */
117+ * status = 'pending'
118+ * ```
119+ */
120+ protected fun isElementAfterConditionLoopDirective (): Boolean =
121+ (parentBlock as ? SqlElConditionLoopCommentBlock )?.let { parent ->
122+ parent.childBlocks.firstOrNull() == this &&
123+ (parent.parentBlock is SqlNewGroupBlock || parent.parentBlock is SqlElConditionLoopCommentBlock )
124+ } == true
125+
126+ protected fun isFirstChildConditionLoopDirective (): Boolean = childBlocks.firstOrNull() is SqlElConditionLoopCommentBlock
127+
84128 fun getChildBlocksDropLast (
85129 dropIndex : Int = 1,
86130 skipCommentBlock : Boolean = true,
@@ -121,31 +165,17 @@ open class SqlBlock(
121165 fun isEnableFormat (): Boolean = enableFormat
122166
123167 open fun isSaveSpace (lastGroup : SqlBlock ? ): Boolean =
124- parentBlock?.let { parent ->
125- when (parent) {
126- is SqlElConditionLoopCommentBlock -> shouldSaveSpaceForConditionLoop(parent)
127- is SqlNewGroupBlock -> shouldSaveSpaceForNewGroup(parent)
128- else -> false
168+ when (lastGroup) {
169+ is SqlNewGroupBlock -> shouldSaveSpaceForNewGroup(lastGroup)
170+ else -> {
171+ shouldSaveSpaceForConditionLoop()
129172 }
130173 } == true
131174
132- private fun shouldSaveSpaceForConditionLoop (parent : SqlElConditionLoopCommentBlock ): Boolean {
133- val prevBlock = prevBlocks.lastOrNull { it !is SqlDefaultCommentBlock }
134- val isPrevBlockElseOrEnd =
135- prevBlock is SqlElConditionLoopCommentBlock &&
136- (prevBlock.conditionType.isElse() || prevBlock.conditionType.isEnd())
137- val hasNoChildrenExceptLast = parent.childBlocks.dropLast(1 ).isEmpty()
138- if (parent.conditionType.isElse()) {
139- return prevBlocks.isEmpty()
140- }
141-
142- val isConditionDirectiveParentGroup =
143- parent.parentBlock?.let { grand ->
144- grand is SqlNewGroupBlock
145- } == true
146-
147- return isPrevBlockElseOrEnd || (hasNoChildrenExceptLast && isConditionDirectiveParentGroup)
148- }
175+ private fun shouldSaveSpaceForConditionLoop (): Boolean =
176+ isConditionLoopDirectiveRegisteredBeforeParent() ||
177+ isElementAfterConditionLoopDirective() ||
178+ isFirstChildConditionLoopDirective()
149179
150180 private fun shouldSaveSpaceForNewGroup (parent : SqlNewGroupBlock ): Boolean {
151181 val prevWord = prevBlocks.lastOrNull { it !is SqlCommentBlock }
@@ -174,6 +204,8 @@ open class SqlBlock(
174204
175205 /* *
176206 * Creates the indentation length for the block.
207+ *
208+ * @return The number of spaces to use for indentation
177209 */
178210 open fun createBlockIndentLen (): Int = 0
179211
@@ -183,18 +215,24 @@ open class SqlBlock(
183215
184216 /* *
185217 * Creates a spacing builder for custom spacing rules.
218+ *
219+ * @return A new instance of SqlCustomSpacingBuilder
186220 */
187221 protected open fun createSpacingBuilder (): SqlCustomSpacingBuilder = SqlCustomSpacingBuilder ()
188222
189223 override fun buildChildren (): List <Block ?>? = emptyList()
190224
191225 /* *
192226 * Determines whether to adjust the indentation on pressing Enter.
227+ *
228+ * @return true if indentation should be adjusted on Enter, false otherwise
193229 */
194230 fun isAdjustIndentOnEnter (): Boolean = formatMode == FormattingMode .ADJUST_INDENT_ON_ENTER && ! isEnableFormat()
195231
196232 /* *
197233 * Returns the indentation for the block.
234+ *
235+ * @return The indent to apply to this block, or null if no indentation should be applied
198236 */
199237 override fun getIndent (): Indent ? =
200238 if (isAdjustIndentOnEnter()) {
@@ -210,6 +248,8 @@ open class SqlBlock(
210248
211249 /* *
212250 * Returns the child indentation for the block.
251+ *
252+ * @return The indent to apply to child blocks
213253 */
214254 override fun getChildIndent (): Indent ? =
215255 if (isEnableFormat()) {
@@ -224,6 +264,8 @@ open class SqlBlock(
224264
225265 /* *
226266 * Determines whether the block is a leaf node.
267+ *
268+ * @return true if this block has no child nodes, false otherwise
227269 */
228270 override fun isLeaf (): Boolean = myNode.firstChildNode == null
229271}
0 commit comments