@@ -67,21 +67,28 @@ open class SqlBlock(
6767 open val childBlocks = mutableListOf<SqlBlock >()
6868 open var prevBlocks = emptyList<SqlBlock >()
6969
70+ companion object {
71+ private const val DEFAULT_INDENT_SIZE = 4
72+ private const val DEFAULT_TEXT_LENGTH_INCREMENT = 1
73+ private val EXCLUDED_FROM_TEXT_LENGTH = setOf (SqlTypes .DOT , SqlTypes .RIGHT_PAREN )
74+ private val SPACING_ONE = Spacing .createSpacing(1 , 1 , 0 , true , 0 )
75+ private val SPACING_ZERO = Spacing .createSpacing(0 , 0 , 0 , true , 0 )
76+ private val SPACING_ONE_NO_KEEP = Spacing .createSpacing(1 , 1 , 0 , false , 0 )
77+ }
78+
7079 fun getChildrenTextLen (): Int = childBlocks.sumOf { child -> calculateChildTextLength(child) }
7180
7281 private fun calculateChildTextLength (child : SqlBlock ): Int {
7382 val nonCommentChildren = child.childBlocks.filterNot { it is SqlDefaultCommentBlock }
7483
75- if (nonCommentChildren.isNotEmpty()) {
76- return child.getChildrenTextLen() + child.getNodeText().length
84+ return when {
85+ nonCommentChildren.isNotEmpty() -> child.getChildrenTextLen() + child.getNodeText().length
86+ isExcludedFromTextLength(child) -> 0
87+ else -> child.getNodeText().length + DEFAULT_TEXT_LENGTH_INCREMENT
7788 }
78- if (isExcludedFromTextLength(child)) {
79- return 0
80- }
81- return child.getNodeText().length + 1
8289 }
8390
84- private fun isExcludedFromTextLength (block : SqlBlock ): Boolean = block.node.elementType in setOf ( SqlTypes . DOT , SqlTypes . RIGHT_PAREN )
91+ private fun isExcludedFromTextLength (block : SqlBlock ): Boolean = block.node.elementType in EXCLUDED_FROM_TEXT_LENGTH
8592
8693 /* *
8794 * Checks if a conditional loop directive is registered before the parent block.
@@ -123,13 +130,19 @@ open class SqlBlock(
123130 (parent.parentBlock is SqlNewGroupBlock || parent.parentBlock is SqlElConditionLoopCommentBlock )
124131 } == true
125132
126- protected fun isElementAfterConditionLoopEnd (): Boolean =
127- (
133+ protected fun isElementAfterConditionLoopEnd (): Boolean {
134+ val prevChildren =
128135 prevBlocks
129- .lastOrNull ()
136+ .firstOrNull ()
130137 ?.childBlocks
131- ?.firstOrNull() as ? SqlElConditionLoopCommentBlock
132- )?.conditionEnd != null
138+
139+ val firstConditionBlock = (prevChildren?.firstOrNull() as ? SqlElConditionLoopCommentBlock )
140+ val endBlock = firstConditionBlock?.conditionEnd
141+ if (endBlock == null ) return false
142+ val lastBlock = prevChildren.lastOrNull()
143+
144+ return endBlock.node.startOffset > (lastBlock?.node?.startOffset ? : 0 )
145+ }
133146
134147 protected fun isFirstChildConditionLoopDirective (): Boolean = childBlocks.firstOrNull() is SqlElConditionLoopCommentBlock
135148
@@ -179,10 +192,8 @@ open class SqlBlock(
179192 open fun isSaveSpace (lastGroup : SqlBlock ? ): Boolean =
180193 when (lastGroup) {
181194 is SqlNewGroupBlock -> shouldSaveSpaceForNewGroup(lastGroup)
182- else -> {
183- shouldSaveSpaceForConditionLoop()
184- }
185- } == true
195+ else -> shouldSaveSpaceForConditionLoop()
196+ }
186197
187198 private fun shouldSaveSpaceForConditionLoop (): Boolean =
188199 isConditionLoopDirectiveRegisteredBeforeParent() ||
@@ -197,15 +208,22 @@ open class SqlBlock(
197208 return false
198209 }
199210
200- return isFollowedByConditionLoop() || isPrecededByConditionLoop (parent)
211+ return hasConditionLoopAround (parent)
201212 }
202213
203214 private fun isNonBreakingKeywordCombination (
204215 parent : SqlNewGroupBlock ,
205216 prevWord : SqlBlock ? ,
206- ): Boolean =
207- SqlKeywordUtil .isSetLineKeyword(getNodeText(), parent.getNodeText()) ||
208- SqlKeywordUtil .isSetLineKeyword(getNodeText(), prevWord?.getNodeText() ? : " " )
217+ ): Boolean {
218+ val currentText = getNodeText()
219+ val parentText = parent.getNodeText()
220+ val prevText = prevWord?.getNodeText() ? : " "
221+
222+ return SqlKeywordUtil .isSetLineKeyword(currentText, parentText) ||
223+ SqlKeywordUtil .isSetLineKeyword(currentText, prevText)
224+ }
225+
226+ private fun hasConditionLoopAround (parent : SqlNewGroupBlock ): Boolean = isFollowedByConditionLoop() || isPrecededByConditionLoop(parent)
209227
210228 private fun isFollowedByConditionLoop (): Boolean = childBlocks.lastOrNull() is SqlElConditionLoopCommentBlock
211229
@@ -265,158 +283,67 @@ open class SqlBlock(
265283 /* *
266284 * Creates a spacing builder specifically for directive block comments.
267285 */
268- protected fun createBlockDirectiveCommentSpacingBuilder (): SqlCustomSpacingBuilder =
269- SqlCustomSpacingBuilder ()
270- .withSpacing(
271- SqlTypes .BLOCK_COMMENT_START ,
272- SqlTypes .EL_ID_EXPR ,
273- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
274- ).withSpacing(
275- SqlTypes .BLOCK_COMMENT_START ,
276- SqlTypes .EL_PRIMARY_EXPR ,
277- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
278- ).withSpacing(
279- SqlTypes .BLOCK_COMMENT_START ,
280- SqlTypes .EL_STRING ,
281- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
282- ).withSpacing(
283- SqlTypes .BLOCK_COMMENT_START ,
284- SqlTypes .EL_NUMBER ,
285- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
286- ).withSpacing(
287- SqlTypes .BLOCK_COMMENT_START ,
288- SqlTypes .BOOLEAN ,
289- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
290- ).withSpacing(
291- SqlTypes .BLOCK_COMMENT_START ,
292- SqlTypes .EL_NULL ,
293- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
294- ).withSpacing(
295- SqlTypes .BLOCK_COMMENT_START ,
296- SqlTypes .EL_FIELD_ACCESS_EXPR ,
297- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
298- ).withSpacing(
299- SqlTypes .BLOCK_COMMENT_START ,
300- SqlTypes .EL_STATIC_FIELD_ACCESS_EXPR ,
301- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
302- ).withSpacing(
303- SqlTypes .BLOCK_COMMENT_START ,
304- SqlTypes .HASH ,
305- Spacing .createSpacing(0 , 0 , 0 , true , 0 ),
306- ).withSpacing(
307- SqlTypes .HASH ,
308- SqlTypes .EL_ID_EXPR ,
309- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
310- ).withSpacing(
311- SqlTypes .HASH ,
312- SqlTypes .EL_PRIMARY_EXPR ,
313- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
314- ).withSpacing(
315- SqlTypes .HASH ,
316- SqlTypes .EL_STRING ,
317- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
318- ).withSpacing(
319- SqlTypes .HASH ,
320- SqlTypes .EL_NUMBER ,
321- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
322- ).withSpacing(
323- SqlTypes .HASH ,
324- SqlTypes .BOOLEAN ,
325- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
326- ).withSpacing(
327- SqlTypes .HASH ,
328- SqlTypes .EL_NULL ,
329- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
330- ).withSpacing(
331- SqlTypes .HASH ,
332- SqlTypes .EL_FIELD_ACCESS_EXPR ,
333- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
334- ).withSpacing(
335- SqlTypes .HASH ,
336- SqlTypes .EL_STATIC_FIELD_ACCESS_EXPR ,
337- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
338- ).withSpacing(
339- SqlTypes .BLOCK_COMMENT_START ,
340- SqlTypes .CARET ,
341- Spacing .createSpacing(0 , 0 , 0 , true , 0 ),
342- ).withSpacing(
343- SqlTypes .CARET ,
286+ protected open fun createBlockDirectiveCommentSpacingBuilder (): SqlCustomSpacingBuilder {
287+ val builder = SqlCustomSpacingBuilder ()
288+
289+ // Types that need spacing after BLOCK_COMMENT_START
290+ val typesNeedingSpaceAfterStart =
291+ listOf (
344292 SqlTypes .EL_ID_EXPR ,
345- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
346- ).withSpacing(
347- SqlTypes .CARET ,
348293 SqlTypes .EL_PRIMARY_EXPR ,
349- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
350- ).withSpacing(
351- SqlTypes .CARET ,
352294 SqlTypes .EL_STRING ,
353- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
354- ).withSpacing(
355- SqlTypes .CARET ,
356295 SqlTypes .EL_NUMBER ,
357- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
358- ).withSpacing(
359- SqlTypes .CARET ,
360296 SqlTypes .BOOLEAN ,
361- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
362- ).withSpacing(
363- SqlTypes .CARET ,
364297 SqlTypes .EL_NULL ,
365- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
366- ).withSpacing(
367- SqlTypes .CARET ,
368- SqlTypes .EL_FIELD_ACCESS_EXPR ,
369- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
370- ).withSpacing(
371- SqlTypes .CARET ,
372- SqlTypes .EL_STATIC_FIELD_ACCESS_EXPR ,
373- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
374- ).withSpacing(
375- SqlTypes .BLOCK_COMMENT_CONTENT ,
376- SqlTypes .BLOCK_COMMENT_END ,
377- Spacing .createSpacing(0 , 0 , 0 , true , 0 ),
378- ).withSpacing(
379298 SqlTypes .EL_FIELD_ACCESS_EXPR ,
380- SqlTypes .OTHER ,
381- Spacing .createSpacing(1 , 1 , 0 , false , 0 ),
382- ).withSpacing(
383299 SqlTypes .EL_STATIC_FIELD_ACCESS_EXPR ,
384- SqlTypes .OTHER ,
385- Spacing .createSpacing(1 , 1 , 0 , false , 0 ),
386- ).withSpacing(
300+ )
301+
302+ // Types that need spacing before BLOCK_COMMENT_END
303+ val typesNeedingSpaceBeforeEnd =
304+ listOf (
387305 SqlTypes .EL_ID_EXPR ,
388- SqlTypes .BLOCK_COMMENT_END ,
389- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
390- ).withSpacing(
391306 SqlTypes .EL_PRIMARY_EXPR ,
392- SqlTypes .BLOCK_COMMENT_END ,
393- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
394- ).withSpacing(
395307 SqlTypes .STRING ,
396- SqlTypes .BLOCK_COMMENT_END ,
397- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
398- ).withSpacing(
399308 SqlTypes .EL_NUMBER ,
400- SqlTypes .BLOCK_COMMENT_END ,
401- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
402- ).withSpacing(
403309 SqlTypes .EL_NULL ,
404- SqlTypes .BLOCK_COMMENT_END ,
405- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
406- ).withSpacing(
407310 SqlTypes .BOOLEAN ,
408- SqlTypes .BLOCK_COMMENT_END ,
409- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
410- ).withSpacing(
411311 SqlTypes .EL_FIELD_ACCESS_EXPR ,
412- SqlTypes .BLOCK_COMMENT_END ,
413- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
414- ).withSpacing(
415312 SqlTypes .EL_STATIC_FIELD_ACCESS_EXPR ,
416- SqlTypes .BLOCK_COMMENT_END ,
417- Spacing .createSpacing(1 , 1 , 0 , true , 0 ),
418313 )
419314
315+ // Add spacing rules for BLOCK_COMMENT_START
316+ typesNeedingSpaceAfterStart.forEach { type ->
317+ builder.withSpacing(SqlTypes .BLOCK_COMMENT_START , type, SPACING_ONE )
318+ }
319+
320+ // Special cases for BLOCK_COMMENT_START
321+ builder.withSpacing(SqlTypes .BLOCK_COMMENT_START , SqlTypes .HASH , SPACING_ZERO )
322+ builder.withSpacing(SqlTypes .BLOCK_COMMENT_START , SqlTypes .CARET , SPACING_ZERO )
323+
324+ // Add spacing rules for HASH
325+ typesNeedingSpaceAfterStart.forEach { type ->
326+ builder.withSpacing(SqlTypes .HASH , type, SPACING_ONE )
327+ }
328+
329+ // Add spacing rules for CARET
330+ typesNeedingSpaceAfterStart.forEach { type ->
331+ builder.withSpacing(SqlTypes .CARET , type, SPACING_ONE )
332+ }
333+
334+ // Special spacing rules
335+ builder.withSpacing(SqlTypes .BLOCK_COMMENT_CONTENT , SqlTypes .BLOCK_COMMENT_END , SPACING_ZERO )
336+ builder.withSpacing(SqlTypes .EL_FIELD_ACCESS_EXPR , SqlTypes .OTHER , SPACING_ONE_NO_KEEP )
337+ builder.withSpacing(SqlTypes .EL_STATIC_FIELD_ACCESS_EXPR , SqlTypes .OTHER , SPACING_ONE_NO_KEEP )
338+
339+ // Add spacing rules before BLOCK_COMMENT_END
340+ typesNeedingSpaceBeforeEnd.forEach { type ->
341+ builder.withSpacing(type, SqlTypes .BLOCK_COMMENT_END , SPACING_ONE )
342+ }
343+
344+ return builder
345+ }
346+
420347 /* *
421348 * Returns the child indentation for the block.
422349 *
@@ -429,10 +356,6 @@ open class SqlBlock(
429356 Indent .getSpaceIndent(0 )
430357 }
431358
432- companion object {
433- private const val DEFAULT_INDENT_SIZE = 4
434- }
435-
436359 /* *
437360 * Determines whether the block is a leaf node.
438361 *
0 commit comments