diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt index dc067b56..15c92a6d 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt @@ -63,9 +63,17 @@ open class SqlBlock( var groupIndentLen: Int, ) + // Maintain the conditional loop directive block associated with itself. + var conditionLoopDirective: SqlElConditionLoopCommentBlock? = null + + // A flag that exists within a conditional loop directive but is not associated with the directive + // (representing the top element of multiple lines). + var multipleInlineDirective = false + open var parentBlock: SqlBlock? = null open val childBlocks = mutableListOf() open var prevBlocks = emptyList() + open val offset = 0 companion object { private const val DEFAULT_INDENT_SIZE = 4 @@ -93,76 +101,6 @@ open class SqlBlock( private fun isExcludedFromTextLength(block: SqlBlock): Boolean = block.node.elementType in EXCLUDED_FROM_TEXT_LENGTH - /** - * Checks if a conditional loop directive is registered before the parent block. - * - * @note - * If the next element after a conditional directive is not a conditional directive block, - * the directive becomes a child of the next element block. - * Therefore, if the first element in [childBlocks] is a conditional directive, - * it can be determined that—syntactically—the conditional directive was placed immediately before the current block. - */ - protected fun isConditionLoopDirectiveRegisteredBeforeParent(): Boolean { - val firstPrevBlock = (prevBlocks.lastOrNull() as? SqlElConditionLoopCommentBlock) - parentBlock?.let { parent -> - return (childBlocks.firstOrNull() as? SqlElConditionLoopCommentBlock)?.isBeforeParentBlock() == true || - firstPrevBlock != null && - firstPrevBlock.conditionEnd != null && - firstPrevBlock.node.startOffset > parent.node.startOffset - } - return false - } - - /** - * Determines if this is the element immediately after a conditional loop directive. - * - * @note - * The parent conditional loop directive becomes a child of the element immediately after the conditional loop directive. - * In the following case, "%if" is a child of "status", and the following "=" and "'pending'" are children of "%if". - * Therefore, set the condition to break line only when the parent of the conditional loop directive is a group block. - * - * @example - * ```sql - * WHERE -- grand - * /*%if status == "pending" */ -- parent - * status = 'pending' -- child - * ``` - */ - protected fun isElementAfterConditionLoopDirective(): Boolean = - (parentBlock as? SqlElConditionLoopCommentBlock)?.let { parent -> - parent.childBlocks.firstOrNull() == this && - (parent.parentBlock is SqlNewGroupBlock || parent.isParentConditionLoopDirective()) - } == true - - protected fun isElementAfterConditionLoopEnd(): Boolean { - val prevChildren = - prevBlocks - .firstOrNull() - ?.childBlocks - - val firstConditionBlock = prevChildren?.firstOrNull { it is SqlElConditionLoopCommentBlock } as? SqlElConditionLoopCommentBlock - val endBlock = - findConditionEndBlock(firstConditionBlock) - if (endBlock == null) return false - val lastBlock = prevBlocks.lastOrNull() - - return endBlock.node.startOffset > (lastBlock?.node?.startOffset ?: 0) - } - - private fun findConditionEndBlock(firstConditionBlock: SqlElConditionLoopCommentBlock?): SqlElConditionLoopCommentBlock? = - ( - firstConditionBlock?.conditionEnd - ?: ( - firstConditionBlock?.childBlocks?.lastOrNull { - it is SqlElConditionLoopCommentBlock - } as? SqlElConditionLoopCommentBlock - )?.conditionEnd - ) - - fun isParentConditionLoopDirective(): Boolean = parentBlock is SqlElConditionLoopCommentBlock - - protected fun isFirstChildConditionLoopDirective(): Boolean = childBlocks.firstOrNull() is SqlElConditionLoopCommentBlock - fun getChildBlocksDropLast( dropIndex: Int = 1, skipCommentBlock: Boolean = true, @@ -185,11 +123,103 @@ open class SqlBlock( 0, ) + /** + * Calculate indentation and line breaks based on the parent block and conditional loop directives with no dependency target set. + * @param lastGroup The last group block + */ open fun setParentGroupBlock(lastGroup: SqlBlock?) { parentBlock = lastGroup - prevBlocks = parentBlock?.childBlocks?.toList() ?: emptyList() + setPrevBlocks() parentBlock?.addChildBlock(this) setParentPropertyBlock(lastGroup) + setIndentLen() + } + + fun setPrevBlocks(parent: SqlBlock? = parentBlock) { + parent?.let { p -> + // Retrieve the first conditional loop directive and the closing tag of the last conditional loop directive. + val firstConditionStart = p.childBlocks.firstOrNull { it.conditionLoopDirective != null }?.conditionLoopDirective + val lastConditionEnd = + p.childBlocks + .lastOrNull { + it.conditionLoopDirective != null && + it.conditionLoopDirective?.conditionEnd != null + }?.conditionLoopDirective + ?.conditionEnd + var openDirective: SqlElConditionLoopCommentBlock? = null + + val filterBlockInlineOpenDirectives = + if (firstConditionStart != null && lastConditionEnd != null) { + p.childBlocks.filterNot { + it.node.startOffset in + (firstConditionStart.node.startOffset until lastConditionEnd.node.startOffset) + } + } else if (firstConditionStart != null) { + openDirective = firstConditionStart + p.childBlocks.filter { it.node.startOffset >= firstConditionStart.node.startOffset } + } else { + p.childBlocks + } + + prevBlocks = filterBlockInlineOpenDirectives.filter { it != this } + } + } + + /** + * Indentation calculation + * + * * When `multipleInlineDirective` is **true**: sibling blocks whose parent is **outside** the conditional loop directive. + * * When `multipleInlineDirective` is **false**: sibling blocks whose parent is **inside** the conditional loop directive, or the block body that the conditional loop directive depends on. + * + */ + protected fun setIndentLen(baseDirective: SqlElConditionLoopCommentBlock? = conditionLoopDirective): Int { + indent.indentLen = + if (multipleInlineDirective) { + baseDirective?.indent?.indentLen ?: indent.indentLen + } else { + if (baseDirective?.getDependsOnBlock() == this) { + baseDirective.indent.indentLen // The block body that the conditional loop directive depends on. + } else { + createBlockIndentLen() // Sibling blocks whose parent is within a conditional loop directive. + } + } + return indent.indentLen + } + + fun createBlockIndentLenDirective( + parent: SqlBlock?, + dependDirective: SqlElConditionLoopCommentBlock?, + ) { + val dependDirectiveOnBlock = dependDirective?.getDependsOnBlock() + if (dependDirectiveOnBlock == null) { + conditionLoopDirective = dependDirective + conditionLoopDirective?.setDependsOnBlock(this) + conditionLoopDirective?.createBlockIndentLenFromDependOn(this) + } + setPrevBlocks(parent) + // Check its own parent block and the parent of the block that `notDependDirective` depends on, + // and adjust the indentation as needed so that it fits within the conditional loop directive block. + val directiveDependent = conditionLoopDirective?.getDependsOnBlock() + if (directiveDependent == null || parent == directiveDependent.parentBlock) { + // Search among sibling blocks for those associated with a conditional loop directive. + // Even if a sibling block is associated with a conditional loop directive, + // there are cases where the indentation is aligned with the parent rather than the conditional loop directive. + val inlineDirectiveParentBlock = + parent?.let { p -> p.node.startOffset >= (dependDirective?.node?.startOffset ?: 0) } == true + multipleInlineDirective = dependDirective?.getDependsOnBlock() != this && !inlineDirectiveParentBlock + setIndentLen(dependDirective) + } + } + + /** + * Trace back from the associated directive and recalculate the indentation of the nested directives. + */ + fun recalculateDirectiveIndent() { + conditionLoopDirective?.let { directive -> + directive.recalculateIndentLen(createBlockIndentLen()) + indent.indentLen = directive.indent.indentLen + indent.groupIndentLen = createGroupIndentLen() + } } open fun setParentPropertyBlock(lastGroup: SqlBlock?) { @@ -206,18 +236,15 @@ open class SqlBlock( fun isEnableFormat(): Boolean = enableFormat + /** + * Block-specific line break determination. + */ open fun isSaveSpace(lastGroup: SqlBlock?): Boolean = when (lastGroup) { is SqlNewGroupBlock -> shouldSaveSpaceForNewGroup(lastGroup) - else -> shouldSaveSpaceForConditionLoop() + else -> false } - private fun shouldSaveSpaceForConditionLoop(): Boolean = - isConditionLoopDirectiveRegisteredBeforeParent() || - isElementAfterConditionLoopDirective() || - isFirstChildConditionLoopDirective() || - isElementAfterConditionLoopEnd() - private fun shouldSaveSpaceForNewGroup(parent: SqlNewGroupBlock): Boolean { val prevWord = prevBlocks.lastOrNull { it !is SqlCommentBlock } @@ -250,16 +277,16 @@ open class SqlBlock( lastPrevBlock.node.psi.startOffset > parent.node.psi.startOffset } - protected fun getLastBlockHasConditionLoopDirective(): SqlElConditionLoopCommentBlock? = - (prevBlocks.lastOrNull()?.childBlocks?.firstOrNull() as? SqlElConditionLoopCommentBlock) - /** - * Creates the indentation length for the block. - * + * Set the indentation for line breaks caused by conditional loop directives based on the parent block and the conditional loop directive. * @return The number of spaces to use for indentation */ open fun createBlockIndentLen(): Int = 0 + /** + * Calculate the indentation to apply to its own child blocks. + * @return The number of spaces to use for child block indentation + */ open fun createGroupIndentLen(): Int = 0 open fun getBlock(child: ASTNode): SqlBlock = this @@ -329,31 +356,25 @@ open class SqlBlock( SqlTypes.EL_STATIC_FIELD_ACCESS_EXPR, ) - // Add spacing rules for BLOCK_COMMENT_START typesNeedingSpaceAfterStart.forEach { type -> builder.withSpacing(SqlTypes.BLOCK_COMMENT_START, type, SPACING_ONE) } - // Special cases for BLOCK_COMMENT_START builder.withSpacing(SqlTypes.BLOCK_COMMENT_START, SqlTypes.HASH, SPACING_ZERO) builder.withSpacing(SqlTypes.BLOCK_COMMENT_START, SqlTypes.CARET, SPACING_ZERO) - // Add spacing rules for HASH typesNeedingSpaceAfterStart.forEach { type -> builder.withSpacing(SqlTypes.HASH, type, SPACING_ONE) } - // Add spacing rules for CARET typesNeedingSpaceAfterStart.forEach { type -> builder.withSpacing(SqlTypes.CARET, type, SPACING_ONE) } - // Special spacing rules builder.withSpacing(SqlTypes.BLOCK_COMMENT_CONTENT, SqlTypes.BLOCK_COMMENT_END, SPACING_ZERO) builder.withSpacing(SqlTypes.EL_FIELD_ACCESS_EXPR, SqlTypes.OTHER, SPACING_ONE_NO_KEEP) builder.withSpacing(SqlTypes.EL_STATIC_FIELD_ACCESS_EXPR, SqlTypes.OTHER, SPACING_ONE_NO_KEEP) - // Add spacing rules before BLOCK_COMMENT_END typesNeedingSpaceBeforeEnd.forEach { type -> builder.withSpacing(type, SqlTypes.BLOCK_COMMENT_END, SPACING_ONE) } @@ -365,20 +386,13 @@ open class SqlBlock( children: List, parent: SqlBlock, ): Int { - // Add the parent's text length to the indentation if the parent is a conditional loop directive. - val directiveParentIndent = - if (parent is SqlElConditionLoopCommentBlock) { - parent.parentBlock - ?.getNodeText() - ?.length ?: 0 - } else { - 0 - } - var prevBlock: SqlBlock? = null - return children - .filter { it !is SqlDefaultCommentBlock && it !is SqlElConditionLoopCommentBlock } - .sumOf { prev -> + val prevChildren = + children + .filter { it !is SqlDefaultCommentBlock } + + val prevSumLength = + prevChildren.sumOf { prev -> val sum = prev .getChildrenTextLen() @@ -397,8 +411,8 @@ open class SqlBlock( ) prevBlock = prev return@sumOf sum - }.plus(parent.indent.groupIndentLen) - .plus(directiveParentIndent) + } + return prevSumLength.plus(parent.indent.groupIndentLen) } fun isOperationSymbol(): Boolean = diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlFileBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlFileBlock.kt index bb45d5ea..ea8c8a2c 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlFileBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlFileBlock.kt @@ -29,6 +29,7 @@ import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.formatter.common.AbstractBlock import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.elementType +import org.domaframework.doma.intellij.common.util.StringUtil import org.domaframework.doma.intellij.common.util.TypeUtil import org.domaframework.doma.intellij.formatter.block.comma.SqlCommaBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlCommentBlock @@ -61,6 +62,7 @@ import org.domaframework.doma.intellij.formatter.block.other.SqlEscapeBlock import org.domaframework.doma.intellij.formatter.block.other.SqlOtherBlock import org.domaframework.doma.intellij.formatter.block.word.SqlAliasBlock import org.domaframework.doma.intellij.formatter.block.word.SqlArrayWordBlock +import org.domaframework.doma.intellij.formatter.block.word.SqlFunctionGroupBlock import org.domaframework.doma.intellij.formatter.block.word.SqlTableBlock import org.domaframework.doma.intellij.formatter.block.word.SqlWordBlock import org.domaframework.doma.intellij.formatter.builder.SqlBlockBuilder @@ -118,10 +120,18 @@ open class SqlFileBlock( val lastGroup = blockBuilder.getLastGroupTopNodeIndexHistory() if (child !is PsiWhiteSpace) { val childBlock = getBlock(child, prevNonWhiteSpaceNode) + val afterConditionEnd = + isAfterEndDirective( + prevNonWhiteSpaceNode, + childBlock, + lastBlock as? SqlWhitespaceBlock?, + ) prevNonWhiteSpaceNode = childBlock - updateCommentParentAndIdent(childBlock) updateBlockParentAndLAddGroup(childBlock) - updateWhiteSpaceInclude(lastBlock, childBlock, lastGroup) + updateWhiteSpaceInclude(lastBlock, childBlock, lastGroup, afterConditionEnd) + // For else/end, exclude group blocks between if~else~end + removeGroupBlockInConditionLoopBlock(childBlock) + updateCommentParentAndIdent(childBlock) blocks.add(childBlock) } else { if (lastBlock !is SqlLineCommentBlock) { @@ -143,6 +153,27 @@ open class SqlFileBlock( return blocks } + private fun isAfterEndDirective( + prevBlock: SqlBlock?, + childBlock: SqlBlock, + lastBlock: SqlWhitespaceBlock?, + ): Boolean = + ( + prevBlock is SqlElConditionLoopCommentBlock && prevBlock.conditionType.isEnd() && + childBlock !is SqlRightPatternBlock && childBlock !is SqlLineCommentBlock + ) || + (childBlock is SqlLineCommentBlock && lastBlock?.getNodeText()?.contains(StringUtil.LINE_SEPARATE) == true) + + private fun removeGroupBlockInConditionLoopBlock(childBlock: SqlBlock) { + if (childBlock !is SqlElConditionLoopCommentBlock || + childBlock.conditionType.isStartDirective() + ) { + return + } + + blockBuilder.removeGroupForClosedDirective() + } + /** * Creates a block for the given child AST node. */ @@ -191,6 +222,7 @@ open class SqlFileBlock( return blockUtil.getKeywordBlock( child, blockBuilder.getLastGroupTopNodeIndexHistory(), + blockBuilder.getLastNotDependOnConditionOrLoopBlock(), ) } @@ -206,10 +238,16 @@ open class SqlFileBlock( val escapeStrings = listOf("\"", "`", "[", "]") if (escapeStrings.contains(child.text)) { - return if (child.text == "[" && prevBlock is SqlArrayWordBlock) { - SqlArrayListGroupBlock(child, defaultFormatCtx) + if (child.text == "[" && prevBlock is SqlArrayWordBlock) { + return SqlArrayListGroupBlock(child, defaultFormatCtx) } else { - SqlEscapeBlock(child, defaultFormatCtx) + if (child.text == "]") { + val arrayGroup = blockBuilder.getGroupTopNodeIndexHistory().findLast { it is SqlArrayListGroupBlock } + if (arrayGroup != null) { + return SqlRightPatternBlock(child, defaultFormatCtx) + } + } + return SqlEscapeBlock(child, defaultFormatCtx) } } return SqlOtherBlock(child, defaultFormatCtx) @@ -270,16 +308,17 @@ open class SqlFileBlock( commentType == SqlTypes.EL_PARSER_LEVEL_COMMENT || commentType == SqlTypes.BLOCK_COMMENT_CONTENT || child.elementType == SqlTypes.LINE_COMMENT if (!defaultBlockComment) { - if (tempBlock !is SqlElConditionLoopCommentBlock) { - if (lastGroup is SqlWithQueryGroupBlock || lastGroupFilteredDirective is SqlWithQueryGroupBlock) { - return SqlWithCommonTableGroupBlock(child, defaultFormatCtx) - } + if (tempBlock is SqlElConditionLoopCommentBlock) { + return tempBlock } - return if (lastGroup is SqlWithCommonTableGroupBlock) { - SqlWithCommonTableGroupBlock(child, defaultFormatCtx) - } else { - tempBlock + + if (lastGroup is SqlWithQueryGroupBlock || lastGroupFilteredDirective is SqlWithQueryGroupBlock) { + return SqlWithCommonTableGroupBlock(child, defaultFormatCtx) + } + if (lastGroup is SqlWithCommonTableGroupBlock) { + return SqlWithCommonTableGroupBlock(child, defaultFormatCtx) } + return tempBlock } else { return tempBlock } @@ -310,9 +349,10 @@ open class SqlFileBlock( lastBlock: AbstractBlock?, childBlock: SqlBlock, lastGroup: SqlBlock?, + afterConditionEnd: Boolean, ) { if (blocks.isNotEmpty() && lastBlock is SqlWhitespaceBlock) { - if (isSaveWhiteSpace(childBlock, lastGroup)) { + if (isSaveWhiteSpace(childBlock, lastGroup) || afterConditionEnd) { val whiteBlock = lastBlock as SqlBlock whiteBlock.parentBlock = lastGroup } else { @@ -328,7 +368,16 @@ open class SqlFileBlock( private fun isSaveWhiteSpace( childBlock: SqlBlock, lastGroup: SqlBlock?, - ): Boolean = childBlock.isSaveSpace(lastGroup) + ): Boolean = checkSaveSpace(childBlock, lastGroup) + + // Always add a line break when holding condition/loop directives + fun checkSaveSpace( + childBlock: SqlBlock, + lastGroup: SqlBlock?, + ): Boolean { + if (childBlock.conditionLoopDirective != null) return true + return childBlock.isSaveSpace(lastGroup) + } /** * Updates the parent block or registers itself as a new group block based on the class of the target block. @@ -337,7 +386,7 @@ open class SqlFileBlock( val lastGroupBlock = blockBuilder.getLastGroupTopNodeIndexHistory() val lastIndentLevel = lastGroupBlock?.indent?.indentLevel if (lastGroupBlock == null || lastIndentLevel == null) { - blockRelationBuilder.updateGroupBlockAddGroup( + blockRelationBuilder.updateGroupBlockParentAndAddGroup( childBlock, ) return @@ -345,6 +394,18 @@ open class SqlFileBlock( if (childBlock is SqlDefaultCommentBlock) return + val openConditionLoopDirective = blockBuilder.getLastNotDependOnConditionOrLoopBlock() + // Don't set parent for condition/loop directives here + if (childBlock is SqlElConditionLoopCommentBlock) { + // Build parent-child relationships when condition/loop directives are consecutive + // Is the end processing not working because if a5 comes right after else? + if (openConditionLoopDirective != null) { + blockRelationBuilder.updateGroupBlockParentAndAddGroup( + childBlock, + ) + return + } + } when (childBlock) { is SqlKeywordGroupBlock -> { blockRelationBuilder.updateKeywordGroupBlockParentAndAddGroup( @@ -387,13 +448,6 @@ open class SqlFileBlock( ) } - is SqlElConditionLoopCommentBlock -> { - blockRelationBuilder.updateConditionLoopCommentBlockParent( - lastGroupBlock, - childBlock, - ) - } - is SqlEscapeBlock -> { val index = if (lastGroupBlock is SqlArrayListGroupBlock) { @@ -448,8 +502,11 @@ open class SqlFileBlock( if (lastGroupBlock is SqlCommaBlock) { blockBuilder.removeLastGroupTopNodeIndexHistory() } - blockRelationBuilder.updateGroupBlockParentAndAddGroup( + // When inside condition/loop directives, instead of excluding groups at the same level from the list, + // get them with appropriate parent conditions + blockRelationBuilder.updateSqlBlockAndOverIndentLevel( childBlock, + true, ) } @@ -481,13 +538,6 @@ open class SqlFileBlock( return SqlCustomSpacingBuilder().getSpacing(childBlock2) } - if (childBlock1 is SqlWhitespaceBlock && childBlock2.isParentConditionLoopDirective()) { - val child1 = childBlock2.parentBlock as SqlElConditionLoopCommentBlock - SqlCustomSpacingBuilder() - .getSpacingElDirectiveComment(child1, childBlock2) - ?.let { return it } - } - if (childBlock1 is SqlElBlockCommentBlock && childBlock2 !is SqlRightPatternBlock) { SqlCustomSpacingBuilder() .getSpacingElDirectiveComment(childBlock1, childBlock2) @@ -500,7 +550,9 @@ open class SqlFileBlock( ) } - if (childBlock1 is SqlArrayWordBlock && childBlock2 is SqlArrayListGroupBlock) { + if ((childBlock1 is SqlArrayWordBlock && childBlock2 is SqlArrayListGroupBlock) || + (childBlock1 is SqlFunctionGroupBlock && childBlock2 is SqlFunctionParamBlock) + ) { return SqlCustomSpacingBuilder.nonSpacing } @@ -586,6 +638,16 @@ open class SqlFileBlock( return SqlCustomSpacingBuilder().getSpacing(childBlock2) } + if (childBlock1 is SqlWordBlock && childBlock2 is SqlOtherBlock) { + return SqlCustomSpacingBuilder.normalSpacing + } + if (childBlock1 is SqlWhitespaceBlock) { + CreateClauseHandler + .getColumnDefinitionRawGroupSpacing(childBlock1, childBlock2) + ?.let { return it } + return SqlCustomSpacingBuilder().getSpacing(childBlock2) + } + if (childBlock1 !is SqlElSymbolBlock && childBlock1 !is SqlOtherBlock && childBlock2 is SqlOtherBlock) { return SqlCustomSpacingBuilder().getSpacing(childBlock2) } @@ -602,7 +664,7 @@ open class SqlFileBlock( } is SqlFunctionParamBlock -> { - return if (childBlock1.node.elementType in listOf(SqlTypes.FUNCTION_NAME, SqlTypes.WORD)) { + return if (childBlock1.node.elementType in setOf(SqlTypes.FUNCTION_NAME, SqlTypes.WORD)) { SqlCustomSpacingBuilder.nonSpacing } else { SqlCustomSpacingBuilder.normalSpacing @@ -637,18 +699,6 @@ open class SqlFileBlock( ?.let { return it } } - // First apply spacing logic for blocks under specific conditions, - // then execute the general spacing logic for post-line-break blocks at the end. - if (childBlock1 is SqlWhitespaceBlock) { - return when (childBlock2) { - is SqlDefaultCommentBlock, is SqlNewGroupBlock -> { - SqlCustomSpacingBuilder().getSpacing(childBlock2) - } - - else -> SqlCustomSpacingBuilder().getSpacing(childBlock2) - } - } - if (childBlock1 is SqlTableBlock || childBlock1 is SqlAliasBlock) { return SqlCustomSpacingBuilder.normalSpacing } @@ -671,7 +721,7 @@ open class SqlFileBlock( childBlock1 is SqlElSymbolBlock && childBlock2 is SqlElAtSignBlock || childBlock1 is SqlOtherBlock && childBlock2 is SqlOtherBlock || childBlock1 is SqlElSymbolBlock && childBlock2 is SqlOtherBlock || - childBlock1?.isOperationSymbol() == true && childBlock2.isOperationSymbol() + childBlock1 !is SqlRightPatternBlock && childBlock1?.isOperationSymbol() == true && childBlock2.isOperationSymbol() override fun isLeaf(): Boolean = false diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlKeywordBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlKeywordBlock.kt index ff3b9931..a360b08f 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlKeywordBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlKeywordBlock.kt @@ -40,8 +40,6 @@ open class SqlKeywordBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = indentLevel - indent.indentLen = createBlockIndentLen() - indent.groupIndentLen = indent.indentLen.plus(getNodeText().length) } override fun setParentPropertyBlock(lastGroup: SqlBlock?) { @@ -94,12 +92,6 @@ open class SqlKeywordBlock( } ?: 1 } - else -> { - if (isParentConditionLoopDirective()) { - parentBlock?.indent?.groupIndentLen ?: 1 - } else { - parentBlock?.indent?.groupIndentLen?.plus(1) ?: 1 - } - } + else -> parentBlock?.indent?.groupIndentLen?.plus(1) ?: 1 } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlLiteralBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlLiteralBlock.kt index 2f1418be..d081ce44 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlLiteralBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlLiteralBlock.kt @@ -41,7 +41,6 @@ open class SqlLiteralBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.NONE - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -49,10 +48,5 @@ open class SqlLiteralBlock( override fun isLeaf(): Boolean = true - override fun createBlockIndentLen(): Int = - if (isFirstChildConditionLoopDirective() || isParentConditionLoopDirective()) { - parentBlock?.indent?.indentLen ?: 0 - } else { - 0 - } + override fun createBlockIndentLen(): Int = parentBlock?.indent?.indentLen ?: 0 } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlRightPatternBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlRightPatternBlock.kt index 79eee5cd..f644c896 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlRightPatternBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlRightPatternBlock.kt @@ -22,7 +22,6 @@ import org.domaframework.doma.intellij.formatter.block.comment.SqlCommentBlock import org.domaframework.doma.intellij.formatter.block.conflict.SqlConflictExpressionSubGroupBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnDefinitionRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.condition.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateTableColumnDefinitionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.insert.SqlInsertColumnGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.insert.SqlInsertValueGroupBlock @@ -32,6 +31,7 @@ import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlU import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlUpdateSetGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlUpdateValueGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithQuerySubGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlDataTypeParamBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlFunctionParamBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock @@ -74,13 +74,13 @@ open class SqlRightPatternBlock( SqlUpdateValueGroupBlock::class, SqlCreateTableColumnDefinitionGroupBlock::class, SqlInsertValueGroupBlock::class, + SqlWithQuerySubGroupBlock::class, ) val NOT_INDENT_EXPECTED_TYPES = listOf( SqlFunctionParamBlock::class, SqlInsertColumnGroupBlock::class, - SqlWithQuerySubGroupBlock::class, SqlConflictExpressionSubGroupBlock::class, ) @@ -128,7 +128,11 @@ open class SqlRightPatternBlock( ) || parent.childBlocks.any { it is SqlValuesGroupBlock } ) { - preSpaceRight = true + if (parent is SqlWithQuerySubGroupBlock) { + preSpaceRight = parent.parentInlineDirective() + } else { + preSpaceRight = true + } return } @@ -165,7 +169,6 @@ open class SqlRightPatternBlock( super.setParentGroupBlock(lastGroup) enableLastRight() indent.indentLevel = IndentType.NONE - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlArrayCommaBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlArrayCommaBlock.kt index f62e30f0..c3c0e5f6 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlArrayCommaBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlArrayCommaBlock.kt @@ -38,7 +38,6 @@ class SqlArrayCommaBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.NONE - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -48,5 +47,5 @@ class SqlArrayCommaBlock( override fun createGroupIndentLen(): Int = indent.indentLen.plus(1) - override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = isParentConditionLoopDirective() + override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = false } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlCommaBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlCommaBlock.kt index ce9b8450..2da9a767 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlCommaBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comma/SqlCommaBlock.kt @@ -19,10 +19,8 @@ import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.common.util.TypeUtil import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.condition.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.insert.SqlInsertColumnGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.insert.SqlInsertValueGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlFromGroupBlock @@ -33,6 +31,7 @@ import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlU import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlUpdateSetGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlUpdateValueGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithColumnGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlFunctionParamBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlParallelListBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock @@ -62,7 +61,6 @@ open class SqlCommaBlock( SqlFunctionParamBlock::class, SqlWithColumnGroupBlock::class, SqlKeywordGroupBlock::class, - SqlElConditionLoopCommentBlock::class, ) private val PARENT_INDENT_SYNC_TYPES = @@ -84,7 +82,6 @@ open class SqlCommaBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.COMMA - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -108,7 +105,7 @@ open class SqlCommaBlock( return parentIndentLen } - // TODO Indent each comma in a value group so that it aligns with the position of the first value row. + // Indent each comma in a value group so that it aligns with the position of the first value row. val parentIndentSingleSpaceTypes = listOf( SqlInsertValueGroupBlock::class, @@ -121,7 +118,6 @@ open class SqlCommaBlock( val notNewLineTypes = listOf( SqlValuesParamGroupBlock::class, - SqlConditionalExpressionGroupBlock::class, ) if (TypeUtil.isExpectedClassType(notNewLineTypes, parent)) return 0 @@ -140,30 +136,13 @@ open class SqlCommaBlock( } else { return when (parent) { is SqlValuesGroupBlock -> parent.indent.indentLen - is SqlElConditionLoopCommentBlock -> { - val firstChild = parent.childBlocks.findLast { it is SqlFunctionParamBlock && it.endPatternBlock == null } - val parentIndent = firstChild?.indent ?: parent.indent - parentIndent.groupIndentLen.plus(1) - } is SqlTableModifySecondGroupBlock -> { - val grand = parent.parentBlock - if (grand is SqlElConditionLoopCommentBlock || - parent.childBlocks.firstOrNull() is SqlElConditionLoopCommentBlock - ) { - parent.indent.indentLen.plus(2) - } else { - parent.indent.indentLen - } + parent.indent.indentLen } else -> { // No indent after ORDER BY within function parameters val grand = parent.parentBlock - val conditionParent = - if (grand is SqlElConditionLoopCommentBlock) { - grand.parentBlock - } else { - grand - } + val conditionParent = grand if (parent is SqlSecondKeywordBlock && conditionParent is SqlFunctionParamBlock) { 0 } else { @@ -183,17 +162,11 @@ open class SqlCommaBlock( if (parent is SqlConditionalExpressionGroupBlock) return false // Don't allow line breaks after ORDER BY within function parameters val grand = parent.parentBlock - val conditionParent = - if (grand is SqlElConditionLoopCommentBlock) { - grand.parentBlock - } else { - grand - } + val conditionParent = grand if (conditionParent is SqlFunctionParamBlock) { return false } - return TypeUtil.isExpectedClassType(EXPECTED_TYPES, parent) || - childBlocks.firstOrNull() is SqlElConditionLoopCommentBlock + return TypeUtil.isExpectedClassType(EXPECTED_TYPES, parent) } return false } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlCommentBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlCommentBlock.kt index 3ddc76fd..f7db7cbb 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlCommentBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlCommentBlock.kt @@ -51,7 +51,6 @@ abstract class SqlCommentBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.NONE - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElBlockCommentBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElBlockCommentBlock.kt index a5387126..09e97376 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElBlockCommentBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElBlockCommentBlock.kt @@ -125,7 +125,6 @@ open class SqlElBlockCommentBlock( override fun createBlockIndentLen(): Int = parentBlock?.let { parent -> when (parent) { - is SqlElConditionLoopCommentBlock -> parent.indent.groupIndentLen is SqlSubQueryGroupBlock -> calculateSubQueryIndent(parent) is SqlValuesGroupBlock -> parent.indent.indentLen is SqlKeywordGroupBlock -> parent.indent.groupIndentLen + 1 @@ -142,7 +141,7 @@ open class SqlElBlockCommentBlock( override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = parentBlock?.let { parent -> - isConditionLoopDirectiveRegisteredBeforeParent() || isParentWithOnlyConditionLoopBlocks(parent) + isParentWithOnlyConditionLoopBlocks(parent) } == true private fun isParentWithOnlyConditionLoopBlocks(parent: SqlBlock): Boolean = diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElConditionLoopCommentBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElConditionLoopCommentBlock.kt index 4da449eb..f6046ef7 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElConditionLoopCommentBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/comment/SqlElConditionLoopCommentBlock.kt @@ -28,13 +28,14 @@ import org.domaframework.doma.intellij.formatter.block.SqlRightPatternBlock import org.domaframework.doma.intellij.formatter.block.SqlUnknownBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.condition.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.insert.SqlInsertQueryGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithCommonTableGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithQueryGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlArrayListGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock +import org.domaframework.doma.intellij.formatter.builder.SqlBlockBuilder import org.domaframework.doma.intellij.formatter.builder.SqlCustomSpacingBuilder import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext import org.domaframework.doma.intellij.psi.SqlCustomElCommentExpr @@ -66,6 +67,20 @@ class SqlElConditionLoopCommentBlock( fun isElse(): Boolean = this == ELSE } + // Temporary storage for making the condition/loop directive one level above the parent depending on the child block + var nestParentBlock: SqlElConditionLoopCommentBlock? = null + + fun setParentSelfNestBlock() { + if (parentBlock == null) { + setParentGroupBlock(nestParentBlock) + } + } + + // Hold dependency block separately from parent + private var dependsOnBlock: SqlBlock? = null + + fun getDependsOnBlock(): SqlBlock? = dependsOnBlock + companion object { const val DIRECTIVE_INDENT_STEP = 2 private const val DEFAULT_INDENT_OFFSET = 1 @@ -77,7 +92,6 @@ class SqlElConditionLoopCommentBlock( ) } - var tempParentBlock: SqlBlock? = null val conditionType: SqlConditionLoopCommentBlockType = initConditionOrLoopType(node) var conditionStart: SqlElConditionLoopCommentBlock? = null var conditionEnd: SqlElConditionLoopCommentBlock? = null @@ -113,27 +127,33 @@ class SqlElConditionLoopCommentBlock( * @note * When a keyword group appears immediately before a conditional or loop directive, and a non-group block appears immediately after, the directive can end up being registered as a child of both. * - * To ensure correct group block generation in the later sub-group block processing, the conditional/loop directive must remain registered as a child of the preceding keyword group. + * To ensure correct group block generation in the later subgroup block processing, the conditional/loop directive must remain registered as a child of the preceding keyword group. * If it is not retained, the resulting group block structure will be inaccurate. * */ override fun setParentGroupBlock(lastGroup: SqlBlock?) { - super.setParentGroupBlock(lastGroup) - - childBlocks.forEach { child -> - if (child is SqlElConditionLoopCommentBlock && child.conditionType.isStartDirective()) { - // If the child is a condition loop directive, align its indentation with the parent directive - child.indent.indentLen = indent.indentLen + DIRECTIVE_INDENT_STEP - } else if (child is SqlLineCommentBlock) { - if (child.hasLineBreakBefore()) { - child.indent.indentLen = indent.groupIndentLen - } else { - child.indent.indentLen = 1 - } - } else { - child.indent.indentLen = indent.groupIndentLen + // When resetting the parent of the parent condition/loop directive, check that the parent is not yet set + if (parentBlock == null) { + parentBlock = lastGroup + if (!conditionType.isStartDirective()) { + (parentBlock as? SqlElConditionLoopCommentBlock)?.conditionEnd = this + createBlockIndentLenFromDependOn(null) + } else if (parentBlock !is SqlElConditionLoopCommentBlock) { + indent.indentLen = initIndentConditionLoopDirective() } } + indent.groupIndentLen = indent.indentLen + } + + fun setParentGroupBlock( + lastGroup: SqlBlock?, + builder: SqlBlockBuilder?, + ) { + // Basically no parent except for nested structures + parentBlock = lastGroup + // Determine your own indent according to the parent's indent. Calculate considering directive nesting + indent.indentLen = calculateIndentLen(builder) + indent.groupIndentLen = indent.indentLen } override fun setParentPropertyBlock(lastGroup: SqlBlock?) { @@ -142,19 +162,65 @@ class SqlElConditionLoopCommentBlock( } } - override fun buildChildren(): MutableList = buildChildBlocks { getBlock(it) } + fun setDependsOnBlock(block: SqlBlock?) { + if (dependsOnBlock != null) return + dependsOnBlock = block + } - override fun getBlock(child: ASTNode): SqlBlock = - when (child.elementType) { - SqlTypes.EL_IF_DIRECTIVE, SqlTypes.EL_ELSEIF_DIRECTIVE, SqlTypes.EL_FOR_DIRECTIVE -> - SqlElBlockCommentBlock( - child, - context, - createBlockDirectiveCommentSpacingBuilder(), - ) + /** + * Calculate indent when dependency is determined + * Called later because dependency indent needs to be calculated first + * If both parent and dependency exist, prioritize parent's indent + * Skip if the passed block is not your own dependency block, just recalculate + */ + fun createBlockIndentLenFromDependOn(hitBlock: SqlBlock?) { + if (hitBlock != null && hitBlock != dependsOnBlock) return + indent.indentLen = calculateIndentLenFromDependOn() + indent.groupIndentLen = indent.indentLen + } - else -> SqlUnknownBlock(child, context) + private fun calculateIndentLenFromDependOn(): Int { + parentBlock?.let { parent -> + val parentGroupIndent = parent.indent.groupIndentLen + return when (parentBlock) { + is SqlElConditionLoopCommentBlock -> { + if (conditionType.isStartDirective()) { + parentGroupIndent.plus(DIRECTIVE_INDENT_STEP) + } else { + parentGroupIndent + } + } + + is SqlSubGroupBlock -> { + parentGroupIndent + } + + else -> parentGroupIndent.plus(1) + } + } + return dependsOnBlock?.indent?.indentLen ?: 0 + } + + /** + * Recalculate nested indents + * Count the number of levels and return to the caller + */ + fun recalculateIndentLen(baseBlockIndent: Int): Int { + if (parentBlock is SqlSubGroupBlock) { + return 1 } + val nestParent = parentBlock as? SqlElConditionLoopCommentBlock + if (nestParent != null) { + val nestLevel = nestParent.recalculateIndentLen(baseBlockIndent) + indent.indentLen = nestParent.indent.indentLen.plus(DIRECTIVE_INDENT_STEP) + indent.groupIndentLen = indent.indentLen + return nestLevel.plus(1) + } + parentBlock = null + indent.indentLen = baseBlockIndent + indent.groupIndentLen = indent.indentLen + return 1 + } override fun getSpacing( child1: Block?, @@ -168,18 +234,57 @@ class SqlElConditionLoopCommentBlock( override fun isLeaf(): Boolean = false - override fun isSaveSpace(lastGroup: SqlBlock?): Boolean { - if (conditionType.isEnd() || conditionType.isElse()) { - return true + override fun buildChildren(): MutableList = buildChildBlocks { getBlock(it) } + + override fun getBlock(child: ASTNode): SqlBlock = + when (child.elementType) { + SqlTypes.EL_IF_DIRECTIVE, SqlTypes.EL_ELSEIF_DIRECTIVE, SqlTypes.EL_FOR_DIRECTIVE -> + SqlElBlockCommentBlock( + child, + context, + createBlockDirectiveCommentSpacingBuilder(), + ) + + else -> SqlUnknownBlock(child, context) } - if (lastGroup is SqlElConditionLoopCommentBlock) { + + override fun isSaveSpace(lastGroup: SqlBlock?): Boolean { + if (!conditionType.isStartDirective()) { return true } - val firstChild = lastGroup?.childBlocks?.firstOrNull() - if (TypeUtil.isExpectedClassType(LINE_BREAK_PARENT_TYPES, lastGroup)) { - return firstChild != null && firstChild != this - } - return firstChild == null || firstChild != this + + // Line break if parent is a condition/loop directive + if (parentBlock is SqlElConditionLoopCommentBlock) return true + + // If `lastGroup` is a comma group or a subgroup, + // do not insert a line break when there is no preceding child (i.e., when this node comes first). + val isExpectedParentOfDependentType = TypeUtil.isExpectedClassType(LINE_BREAK_PARENT_TYPES, lastGroup) + if (isExpectedParentOfDependentType) return lastGroup?.childBlocks?.isNotEmpty() == true + return true + } + + /** + * When directly containing a conditional directive, determine your own indentation as the nest top. + */ + private fun initIndentConditionLoopDirective(): Int = + parentBlock?.let { parent -> + val openConditionLoopDirectiveCount = getOpenDirectiveCount(null) + when (parent) { + is SqlSubGroupBlock -> calculateSubGroupBlockIndent(parent, openConditionLoopDirectiveCount) + is SqlKeywordGroupBlock -> calculateKeywordGroupBlockIndent(parent, openConditionLoopDirectiveCount) + + else -> 0 + } + } ?: 0 + + private fun calculateKeywordGroupBlockIndent( + parent: SqlKeywordGroupBlock, + openConditionLoopDirectiveCount: Int, + ): Int { + val withQuerySpace = (parent as? SqlWithQueryGroupBlock)?.let { 0 } ?: 1 + return parent.indent.groupIndentLen + + openConditionLoopDirectiveCount * DIRECTIVE_INDENT_STEP + + withQuerySpace } /** @@ -189,12 +294,18 @@ class SqlElConditionLoopCommentBlock( * If the element immediately below the directive is not [SqlKeywordGroupBlock] or [SqlSubGroupBlock], * align it to the previous group indent. */ - override fun createBlockIndentLen(): Int { + fun createBlockIndentLen(builder: SqlBlockBuilder?) { + indent.indentLen = calculateIndentLen(builder) + } + + private fun calculateIndentLen(builder: SqlBlockBuilder?): Int { parentBlock?.let { parent -> if (conditionType.isEnd() || conditionType.isElse()) { return parent.indent.indentLen } - val openConditionLoopDirectiveCount = getOpenDirectiveCount(parent) + // Once a parent-child relationship with a conditional directive is established, + // the top-level indentation is already calculated. + val openConditionLoopDirectiveCount = getOpenDirectiveCount(builder) when (parent) { is SqlSubGroupBlock -> return calculateSubGroupBlockIndent(parent, openConditionLoopDirectiveCount) @@ -210,21 +321,7 @@ class SqlElConditionLoopCommentBlock( } } - is SqlKeywordGroupBlock -> { - // At this point, it's not possible to determine whether the parent keyword group appears before or after this block based solely on the parent-child relationship. - // Therefore, determine the position directly using the text offset. - if (isBeforeParentBlock()) { - return parent.indent.indentLen + openConditionLoopDirectiveCount * DIRECTIVE_INDENT_STEP - } - getLastBlockHasConditionLoopDirective()?.let { lastBlock -> - if (lastBlock.conditionEnd != null) { - return lastBlock.indent.indentLen - } - } - val withQuerySpace = if (parent !is SqlWithQueryGroupBlock) 1 else 0 - return parent.indent.groupIndentLen.plus(withQuerySpace) + - openConditionLoopDirectiveCount * DIRECTIVE_INDENT_STEP - } + is SqlKeywordGroupBlock -> return calculateKeywordGroupBlockIndent(parent, openConditionLoopDirectiveCount) else -> return parent.indent.indentLen + openConditionLoopDirectiveCount * DIRECTIVE_INDENT_STEP } } @@ -238,34 +335,19 @@ class SqlElConditionLoopCommentBlock( * Since the current directive is included in the count, * **subtract 1 at the end** to exclude itself. */ - private fun getOpenDirectiveCount(parent: SqlBlock): Int { + private fun getOpenDirectiveCount(builder: SqlBlockBuilder?): Int { + if (parentBlock !is SqlElConditionLoopCommentBlock) return 0 val conditionLoopDirectives: List = - parent - .childBlocks - .filterIsInstance() - .filter { it.conditionEnd == null } - val startDirectives = - conditionLoopDirectives.count { it.conditionType.isStartDirective() } - val endDirectives = conditionLoopDirectives.count { it.conditionType.isEnd() } - val diffCount = startDirectives - endDirectives - return if (diffCount > 0) diffCount - 1 else 0 + builder?.getNotClosedConditionOrLoopBlock() ?: emptyList() + return conditionLoopDirectives.size } /** - * Determine if this conditional loop directive block is positioned before its parent block. + * Indentation calculation when the immediately preceding group is a subgroup block. */ - fun isBeforeParentBlock(): Boolean { - parentBlock?.let { parent -> - return parent.node.startOffset > node.startOffset - } - return false - } - - fun checkConditionLoopDirectiveParentBlock(block: SqlBlock): Boolean = isBeforeParentBlock() && parentBlock == block - private fun calculateSubGroupBlockIndent( parent: SqlSubGroupBlock, - openDirectiveCount: Int, + openDirectiveCount: Int = 0, ): Int { val parentGroupIndentLen = parent.indent.groupIndentLen val grand = parent.parentBlock @@ -274,6 +356,7 @@ class SqlElConditionLoopCommentBlock( return parent.indent.groupIndentLen } + // Set the indentation determined by the parent of the subgroup block. grand?.let { grandParent -> when (grandParent) { is SqlCreateKeywordGroupBlock -> { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/conflict/SqlConflictClauseBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/conflict/SqlConflictClauseBlock.kt index 877cd91a..60fe151c 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/conflict/SqlConflictClauseBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/conflict/SqlConflictClauseBlock.kt @@ -35,7 +35,6 @@ class SqlConflictClauseBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.CONFLICT - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen.plus(getNodeText().length) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlColumnDefinitionRawGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlColumnDefinitionRawGroupBlock.kt index 553b9064..a1e12e21 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlColumnDefinitionRawGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlColumnDefinitionRawGroupBlock.kt @@ -54,7 +54,6 @@ open class SqlColumnDefinitionRawGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlColumnRawGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlColumnRawGroupBlock.kt index 1a111edb..61bb99d9 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlColumnRawGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlColumnRawGroupBlock.kt @@ -39,12 +39,11 @@ class SqlColumnRawGroupBlock( node, context, ) { - private val offset = 1 + override val offset = 1 override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.COLUMN - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = if (isFirstColumnGroup) indent.indentLen else indent.indentLen.plus(1) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlJoinGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlJoinGroupBlock.kt index 795a6c52..e3a4b5a0 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlJoinGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlJoinGroupBlock.kt @@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.option.SqlLateralGroupBlock import org.domaframework.doma.intellij.formatter.util.IndentType import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext @@ -42,20 +41,13 @@ open class SqlJoinGroupBlock( parentBlock = lastGroup parentBlock?.childBlocks?.add(this) indent.indentLevel = IndentType.JOIN - indent.indentLen = createBlockIndentLen() + setIndentLen() indent.groupIndentLen = createGroupIndentLen() } override fun buildChildren(): MutableList = mutableListOf() - override fun createBlockIndentLen(): Int { - return parentBlock?.let { parent -> - if (parent is SqlElConditionLoopCommentBlock) { - return parent.indent.groupIndentLen - } - return parent.indent.groupIndentLen.plus(1) - } ?: 1 - } + override fun createBlockIndentLen(): Int = parentBlock?.indent?.groupIndentLen?.plus(1) ?: 1 override fun createGroupIndentLen(): Int = indent.indentLen diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlKeywordGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlKeywordGroupBlock.kt index a7554b5a..93a905cb 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlKeywordGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlKeywordGroupBlock.kt @@ -20,15 +20,14 @@ import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.common.util.TypeUtil import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.SqlKeywordBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.top.SqlSelectQueryGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithCommonTableGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlFunctionParamBlock -import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock import org.domaframework.doma.intellij.formatter.util.IndentType import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext import org.domaframework.doma.intellij.formatter.util.SqlKeywordUtil +import org.domaframework.doma.intellij.psi.SqlTypes open class SqlKeywordGroupBlock( node: ASTNode, @@ -37,31 +36,24 @@ open class SqlKeywordGroupBlock( ) : SqlNewGroupBlock(node, context) { val topKeywordBlocks: MutableList = mutableListOf(this) var canAddTopKeyword = true + private val topKeywordTypes = + listOf( + SqlKeywordBlock::class, + SqlKeywordGroupBlock::class, + ) fun updateTopKeywordBlocks(block: SqlBlock) { - val lastChild = - getChildBlocksDropLast().lastOrNull() - val topKeywordTypes = - listOf( - SqlKeywordBlock::class, - SqlKeywordGroupBlock::class, - SqlElConditionLoopCommentBlock::class, - ) - - if (lastChild == null || - TypeUtil.isExpectedClassType( - topKeywordTypes, - lastChild, - ) && - canAddTopKeyword - ) { + val hasBlock = topKeywordBlocks.contains(block) + val matchKeywordType = + block.node.elementType == SqlTypes.KEYWORD && + TypeUtil.isExpectedClassType( + topKeywordTypes, + block, + ) + + if (matchKeywordType && canAddTopKeyword && !hasBlock) { topKeywordBlocks.add(block) - } else { - if (block !is SqlElConditionLoopCommentBlock) { - canAddTopKeyword = false - } } - indent.groupIndentLen = createGroupIndentLen() } @@ -74,17 +66,22 @@ open class SqlKeywordGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - val preChildBlock = - if (lastGroup?.indent?.indentLevel == IndentType.FILE) { - null - } else { - lastGroup?.childBlocks?.dropLast(1)?.lastOrNull() - } indent.indentLevel = indentLevel - - val baseIndentLen = getBaseIndentLen(preChildBlock, lastGroup) indent.groupIndentLen = createGroupIndentLen() - indent.indentLen = adjustIndentIfFirstChildIsLineComment(baseIndentLen) + } + + override fun addChildBlock(childBlock: SqlBlock) { + super.addChildBlock(childBlock) + val lastChild = childBlocks.lastOrNull() + val canAppendToLastChild = + lastChild?.node?.elementType == SqlTypes.KEYWORD && + TypeUtil.isExpectedClassType( + topKeywordTypes, + lastChild, + ) + if (canAddTopKeyword) { + canAddTopKeyword = canAppendToLastChild || lastChild == null + } } override fun setParentPropertyBlock(lastGroup: SqlBlock?) { @@ -120,32 +117,8 @@ open class SqlKeywordGroupBlock( override fun buildChildren(): MutableList = mutableListOf() - /** - * Adjust the indent position of the subgroup block element itself if it has a comment - */ - open fun adjustIndentIfFirstChildIsLineComment(baseIndent: Int): Int { - parentBlock?.let { parent -> - if (indent.indentLevel == IndentType.TOP) { - when (parent) { - is SqlSubGroupBlock -> { - return if (parent.isFirstLineComment) { - parent.indent.groupIndentLen.minus(parent.getNodeText().length) - } else { - val newIndentLen = baseIndent.minus(1) - return if (newIndentLen >= 0) newIndentLen else 0 - } - } - - else -> return baseIndent - } - } - } - return baseIndent - } - open fun createBlockIndentLen(preChildBlock: SqlBlock?): Int { parentBlock?.let { parent -> - if (parent is SqlElConditionLoopCommentBlock) return parent.indent.groupIndentLen when (indentLevel) { IndentType.TOP -> { if (SqlKeywordUtil.isSetLineKeyword( @@ -181,15 +154,8 @@ open class SqlKeywordGroupBlock( fun getTotalTopKeywordLength(): Int = topKeywordBlocks.sumOf { it.getNodeText().length.plus(1) }.minus(1) override fun isSaveSpace(lastGroup: SqlBlock?): Boolean { - val conditionLastGroup = - if (isParentConditionLoopDirective()) { - parentBlock?.parentBlock - } else { - lastGroup - } val prevWord = prevBlocks.findLast { it is SqlKeywordBlock || it is SqlKeywordGroupBlock } return !SqlKeywordUtil.isSetLineKeyword(this.getNodeText(), prevWord?.getNodeText() ?: "") && - !SqlKeywordUtil.isSetLineKeyword(this.getNodeText(), conditionLastGroup?.getNodeText() ?: "") && !SqlKeywordUtil.isSetLineKeyword(this.getNodeText(), lastGroup?.getNodeText() ?: "") && lastGroup !is SqlFunctionParamBlock } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/condition/SqlConditionKeywordGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/condition/SqlConditionKeywordGroupBlock.kt index 455ada00..90e66db7 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/condition/SqlConditionKeywordGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/condition/SqlConditionKeywordGroupBlock.kt @@ -17,11 +17,11 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.condition import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineSecondGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.option.SqlSecondOptionKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlWhereGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext @@ -39,7 +39,6 @@ class SqlConditionKeywordGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -55,7 +54,6 @@ class SqlConditionKeywordGroupBlock( val groupLen = parent.indent.groupIndentLen return when (parent) { - is SqlElConditionLoopCommentBlock -> parent.indent.groupIndentLen is SqlSubGroupBlock -> calculateSubGroupIndent(groupLen) is SqlInlineSecondGroupBlock -> calculateInlineSecondIndent(groupLen) else -> parent.indent.groupIndentLen - getNodeText().length diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateKeywordGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateKeywordGroupBlock.kt index d9fcdd37..b3c7ed5b 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateKeywordGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateKeywordGroupBlock.kt @@ -38,7 +38,6 @@ open class SqlCreateKeywordGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.TOP - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen.plus(getNodeText().length) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateTableColumnDefinitionGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateTableColumnDefinitionGroupBlock.kt index f26f4d9a..d9febd91 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateTableColumnDefinitionGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateTableColumnDefinitionGroupBlock.kt @@ -56,7 +56,6 @@ class SqlCreateTableColumnDefinitionGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen.plus(GROUP_INDENT_OFFSET) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateTableColumnDefinitionRawGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateTableColumnDefinitionRawGroupBlock.kt index bd58573c..d814a80f 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateTableColumnDefinitionRawGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateTableColumnDefinitionRawGroupBlock.kt @@ -51,7 +51,6 @@ class SqlCreateTableColumnDefinitionRawGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateViewGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateViewGroupBlock.kt index 50bfe8d3..e0d4927b 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateViewGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/create/SqlCreateViewGroupBlock.kt @@ -40,7 +40,6 @@ open class SqlCreateViewGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.SUB - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = getNodeText().length } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineGroupBlock.kt index 499a9789..c7eda4d6 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineGroupBlock.kt @@ -42,7 +42,6 @@ open class SqlInlineGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.INLINE - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -50,9 +49,7 @@ open class SqlInlineGroupBlock( override fun createBlockIndentLen(): Int = parentBlock?.let { parent -> - if (isParentConditionLoopDirective() || isFirstChildConditionLoopDirective() || - parent is SqlSubGroupBlock - ) { + if (parent is SqlSubGroupBlock) { parent.indent.groupIndentLen } else { parent.indent.groupIndentLen.plus(1) diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineSecondGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineSecondGroupBlock.kt index 0fec8fc4..e4bf3922 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineSecondGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineSecondGroupBlock.kt @@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.inline import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock import org.domaframework.doma.intellij.formatter.util.IndentType import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext @@ -42,7 +41,6 @@ open class SqlInlineSecondGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.INLINE_SECOND - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -57,8 +55,6 @@ open class SqlInlineSecondGroupBlock( if (isEndCase) { val diffTextLength = parent.getNodeText().length.minus(getNodeText().length) parent.indent.indentLen.plus(diffTextLength) - } else if (parent is SqlElConditionLoopCommentBlock) { - parent.indent.groupIndentLen } else { parent.indent.groupIndentLen.plus(1) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/insert/SqlInsertColumnGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/insert/SqlInsertColumnGroupBlock.kt index 0908d812..86b223eb 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/insert/SqlInsertColumnGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/insert/SqlInsertColumnGroupBlock.kt @@ -42,7 +42,6 @@ class SqlInsertColumnGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen.plus(1) updateParentGroupIndentLen() } @@ -69,7 +68,7 @@ class SqlInsertColumnGroupBlock( */ private fun updateParentGroupIndentLen() { parentBlock?.let { parent -> - // TODO Indentation is adjusted on the parent class side + // Indentation is adjusted on the parent class side val parentBaseLen = getParentInsertKeywordsIndentLength(parent) parent.indent.groupIndentLen = parentBaseLen } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlExistsGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlExistsGroupBlock.kt index d0802f3f..818fa454 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlExistsGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlExistsGroupBlock.kt @@ -31,31 +31,14 @@ class SqlExistsGroupBlock( ) : SqlKeywordGroupBlock(node, IndentType.OPTIONS, context) { override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } - override fun createBlockIndentLen(): Int { - parentBlock?.let { parent -> - if (parent.isParentConditionLoopDirective()) { - return parent.indent.groupIndentLen - } - } - return parentBlock?.indent?.groupIndentLen?.plus(1) ?: 1 - } + override fun createBlockIndentLen(): Int = parentBlock?.indent?.groupIndentLen?.plus(1) ?: 1 override fun createGroupIndentLen(): Int { - // If this group is not the top of a line, there must be one space between it and the block before it. - val correctionSpace = - if (isFirstChildConditionLoopDirective() || - isParentConditionLoopDirective() - ) { - 0 - } else { - 1 - } - val parentGroupIndent = parentBlock?.indent?.groupIndentLen ?: 0 - return getTotalTopKeywordLength().plus(parentGroupIndent).plus(correctionSpace) + val parentGroupIndent = parentBlock?.indent?.groupIndentLen?.plus(1) ?: 0 + return getTotalTopKeywordLength().plus(parentGroupIndent) } override fun isSaveSpace(lastGroup: SqlBlock?): Boolean { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlInGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlInGroupBlock.kt index 1e429f24..7a146da6 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlInGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlInGroupBlock.kt @@ -17,7 +17,6 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.option import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.util.IndentType import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext @@ -32,17 +31,11 @@ class SqlInGroupBlock( ) { override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } override fun createBlockIndentLen(): Int { parentBlock?.let { parent -> - if (parent is SqlElConditionLoopCommentBlock && - parent.checkConditionLoopDirectiveParentBlock(this) - ) { - return parent.indent.indentLen - } return calculatePrevBlocksLength(prevBlocks, parent).plus(1) } return 0 @@ -50,11 +43,5 @@ class SqlInGroupBlock( override fun createGroupIndentLen(): Int = indent.indentLen.plus(getNodeText().length) - override fun isSaveSpace(lastGroup: SqlBlock?): Boolean { - if (lastGroup is SqlElConditionLoopCommentBlock) { - if (lastGroup.conditionType.isElse()) return false - return !lastGroup.isBeforeParentBlock() - } - return false - } + override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = false } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlLateralGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlLateralGroupBlock.kt index ceeeae7f..60d7d6dd 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlLateralGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlLateralGroupBlock.kt @@ -17,7 +17,6 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.option import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlFromGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock @@ -36,7 +35,6 @@ class SqlLateralGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -48,7 +46,6 @@ class SqlLateralGroupBlock( override fun createBlockIndentLen(): Int { parentBlock?.let { parent -> - if (parent is SqlElConditionLoopCommentBlock) return parent.indent.groupIndentLen return parent.indent.groupIndentLen.plus(1) } return 0 diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlSecondOptionKeywordGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlSecondOptionKeywordGroupBlock.kt index 88b8e91b..4dde50c6 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlSecondOptionKeywordGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/option/SqlSecondOptionKeywordGroupBlock.kt @@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.option import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.SqlKeywordBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubQueryGroupBlock @@ -30,18 +29,12 @@ open class SqlSecondOptionKeywordGroupBlock( node: ASTNode, context: SqlBlockFormattingContext, ) : SqlKeywordGroupBlock(node, IndentType.SECOND_OPTION, context) { - override fun setParentGroupBlock(lastGroup: SqlBlock?) { - super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() - } - override fun createBlockIndentLen(): Int { parentBlock?.let { parent -> val groupLen = parent.indent.groupIndentLen if (parent.indent.indentLevel == IndentType.FILE) { return 0 } - if (parent is SqlElConditionLoopCommentBlock) return groupLen val subGroupBlock = parent.parentBlock as? SqlSubGroupBlock val newIndent = if (parent is SqlSubQueryGroupBlock) { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/second/SqlSecondKeywordBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/second/SqlSecondKeywordBlock.kt index 1780ed64..86194562 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/second/SqlSecondKeywordBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/second/SqlSecondKeywordBlock.kt @@ -18,24 +18,24 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.second import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.common.util.TypeUtil import org.domaframework.doma.intellij.formatter.block.SqlBlock +import org.domaframework.doma.intellij.formatter.block.SqlKeywordBlock import org.domaframework.doma.intellij.formatter.block.SqlRightPatternBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlFunctionParamBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock import org.domaframework.doma.intellij.formatter.util.IndentType import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext +import org.domaframework.doma.intellij.formatter.util.SqlKeywordUtil open class SqlSecondKeywordBlock( node: ASTNode, context: SqlBlockFormattingContext, ) : SqlKeywordGroupBlock(node, IndentType.SECOND, context) { - private val offset = 0 + override val offset = 0 override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -52,8 +52,6 @@ open class SqlSecondKeywordBlock( 1 } groupLen.plus(space) - } else if (parent is SqlElConditionLoopCommentBlock) { - groupLen } else { groupLen.minus(this.getNodeText().length) } @@ -63,17 +61,19 @@ open class SqlSecondKeywordBlock( override fun isSaveSpace(lastGroup: SqlBlock?): Boolean { parentBlock?.let { parent -> - val conditionParent = - if (parent is SqlElConditionLoopCommentBlock) { - parent.parentBlock - } else { - parent - } - if (conditionParent is SqlFunctionParamBlock) { + if (parent is SqlFunctionParamBlock) { val firstKeywordParam = - conditionParent.childBlocks.firstOrNull { it is SqlNewGroupBlock } + parent.childBlocks.firstOrNull { it is SqlNewGroupBlock } return firstKeywordParam != null && firstKeywordParam != this } else { + val prevKeywordGroupBlock = + prevBlocks.lastOrNull()?.childBlocks?.lastOrNull { + it is SqlKeywordBlock || + it is SqlKeywordGroupBlock + } + if (SqlKeywordUtil.isSetLineKeyword(getNodeText(), prevKeywordGroupBlock?.getNodeText() ?: "")) { + return false + } return super.isSaveSpace(lastGroup) } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlJoinQueriesGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlJoinQueriesGroupBlock.kt index 1c5d0801..1fc2058c 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlJoinQueriesGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlJoinQueriesGroupBlock.kt @@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.top import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.SqlFileBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithQuerySubGroupBlock import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext @@ -31,11 +30,10 @@ class SqlJoinQueriesGroupBlock( context: SqlBlockFormattingContext, ) : SqlTopQueryGroupBlock(node, context) { // TODO Customize offset - private val offset = 0 + override val offset = 0 override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -44,7 +42,6 @@ class SqlJoinQueriesGroupBlock( return when (parent) { is SqlFileBlock -> 0 is SqlWithQuerySubGroupBlock -> parent.indent.groupIndentLen - is SqlElConditionLoopCommentBlock -> createIndentLenInConditionLoopDirective(parent) else -> parent.indent.groupIndentLen.plus(1) } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlSelectQueryGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlSelectQueryGroupBlock.kt index 9bd39f23..0b2fc8ef 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlSelectQueryGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlSelectQueryGroupBlock.kt @@ -38,7 +38,7 @@ class SqlSelectQueryGroupBlock( parentBlock?.addChildBlock(this) setParentPropertyBlock(lastGroup) indent.indentLevel = indentLevel - indent.indentLen = createBlockIndentLen() + setIndentLen() indent.groupIndentLen = createGroupIndentLen() } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlTableModificationKeyword.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlTableModificationKeyword.kt index 5af0b839..a61ecee7 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlTableModificationKeyword.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlTableModificationKeyword.kt @@ -17,7 +17,6 @@ package org.domaframework.doma.intellij.formatter.block.group.keyword.top import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.util.IndentType import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext @@ -38,9 +37,7 @@ class SqlTableModificationKeyword( override fun createBlockIndentLen(): Int { return parentBlock?.let { parent -> val rootBlock = - if (parent is SqlElConditionLoopCommentBlock) { - parent.tempParentBlock - } else if (parent.indent.indentLevel == IndentType.FILE) { + if (parent.indent.indentLevel == IndentType.FILE) { null } else { parent @@ -54,12 +51,5 @@ class SqlTableModificationKeyword( } ?: 0 } - override fun createGroupIndentLen(): Int = - parentBlock?.let { parent -> - if (parent is SqlElConditionLoopCommentBlock) { - parent.indent.indentLen - } else { - getTotalTopKeywordLength() - } - } ?: getTotalTopKeywordLength() + override fun createGroupIndentLen(): Int = getTotalTopKeywordLength() } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlTopQueryGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlTopQueryGroupBlock.kt index 1582bc90..72410b6a 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlTopQueryGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/top/SqlTopQueryGroupBlock.kt @@ -47,7 +47,6 @@ abstract class SqlTopQueryGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = indentLevel - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -56,9 +55,6 @@ abstract class SqlTopQueryGroupBlock( override fun createBlockIndentLen(): Int { parentBlock?.let { parent -> if (parent.indent.indentLevel == IndentType.FILE) return OFFSET - if (parent is SqlElConditionLoopCommentBlock) { - return createIndentLenInConditionLoopDirective(parent) - } var baseIndent = parent.indent.groupIndentLen if (!TypeUtil.isExpectedClassType(PARENT_INDENT_SYNC_TYPES, parent)) { baseIndent = baseIndent.plus(1) @@ -68,38 +64,6 @@ abstract class SqlTopQueryGroupBlock( return 0 } - protected fun createIndentLenInConditionLoopDirective(parent: SqlElConditionLoopCommentBlock): Int { - // When the parent is a conditional directive, adjust the indent considering loop nesting - val parentConditionLoopNests = mutableListOf() - var blockParent: SqlBlock? = parent - parentConditionLoopNests.add(parent) - while (blockParent is SqlElConditionLoopCommentBlock) { - blockParent = blockParent.parentBlock - if (blockParent != null) parentConditionLoopNests.add(blockParent) - } - val prevGroupBlock = parentConditionLoopNests.lastOrNull() - parentConditionLoopNests.dropLast(1).reversed().forEachIndexed { index, p -> - if (index == 0) { - // For the first conditional loop directive, if it has a parent block whose indent level is lower than itself, - // align with the indent of that parent's parent - prevGroupBlock?.let { prev -> - if (prev.indent.indentLevel >= indent.indentLevel) { - p.indent.indentLen = prev.parentBlock?.indent?.indentLen ?: OFFSET - } - } - } else { - // For subsequent conditional loop directives, adjust the indent by the nesting count * 2 - p.indent.indentLen = p.parentBlock - ?.indent - ?.indentLen - ?.plus(2) ?: (index * 2) - } - p.indent.groupIndentLen = p.indent.indentLen - } - - return parent.indent.indentLen - } - override fun isSaveSpace(lastGroup: SqlBlock?): Boolean { if (TypeUtil.isTopLevelExpectedType(lastGroup) && lastGroup !is SqlWithQuerySubGroupBlock && diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateColumnGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateColumnGroupBlock.kt index a281bf5f..8764258f 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateColumnGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateColumnGroupBlock.kt @@ -38,7 +38,6 @@ class SqlUpdateColumnGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen.plus(1) updateParentGroupIndentLen() } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateSetGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateSetGroupBlock.kt index bb0de1f8..66495759 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateSetGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateSetGroupBlock.kt @@ -39,7 +39,6 @@ open class SqlUpdateSetGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.SECOND - indent.indentLen = createBlockIndentLen(null) indent.groupIndentLen = indent.indentLen.plus(getNodeText().length) } @@ -49,7 +48,7 @@ open class SqlUpdateSetGroupBlock( override fun buildChildren(): MutableList = mutableListOf() - override fun createBlockIndentLen(preChildBlock: SqlBlock?): Int = parentBlock?.indent?.groupIndentLen?.minus(getNodeText().length) ?: 0 + override fun createBlockIndentLen(): Int = parentBlock?.indent?.groupIndentLen?.minus(getNodeText().length) ?: 0 override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = true } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateValueGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateValueGroupBlock.kt index d4a0e5c7..8d59d7a4 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateValueGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/update/SqlUpdateValueGroupBlock.kt @@ -37,7 +37,6 @@ class SqlUpdateValueGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithColumnGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithColumnGroupBlock.kt index a87f0714..6fb54d00 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithColumnGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithColumnGroupBlock.kt @@ -26,7 +26,6 @@ class SqlWithColumnGroupBlock( ) : SqlSubGroupBlock(node, context) { override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithCommonTableGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithCommonTableGroupBlock.kt index a89e35fc..754613ed 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithCommonTableGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithCommonTableGroupBlock.kt @@ -19,11 +19,11 @@ import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.common.util.TypeUtil import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlBlockCommentBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlValuesGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock import org.domaframework.doma.intellij.formatter.block.word.SqlWordBlock import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext +import org.domaframework.doma.intellij.psi.SqlTypes class SqlWithCommonTableGroupBlock( node: ASTNode, @@ -39,13 +39,12 @@ class SqlWithCommonTableGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() isFirstTable = findWithQueryChildBlocks() == null } private fun getCommonTableName(): SqlBlock? { - if (getNodeText() == ",") return null + if (node.elementType == SqlTypes.COMMA) return null val expectedTypes = listOf( SqlBlockCommentBlock::class, @@ -74,33 +73,22 @@ class SqlWithCommonTableGroupBlock( } override fun createBlockIndentLen(): Int { - parentBlock?.let { parent -> - val prevBlock = - parent - .getChildBlocksDropLast(skipConditionLoopCommentBlock = false) - .lastOrNull() - return if (prevBlock is SqlElConditionLoopCommentBlock) 4 else 0 - } - return 0 + val baseIndent = if (node.elementType == SqlTypes.COMMA) 0 else offset + return if (conditionLoopDirective == null) baseIndent else offset } override fun createGroupIndentLen(): Int { + val baseIndent = if (conditionLoopDirective == null) 0 else offset parentBlock?.let { parent -> - return getChildBlocksDropLast().sumOf { it.getNodeText().length.plus(1) }.plus(offset) + return getChildBlocksDropLast().sumOf { it.getNodeText().length.plus(1) }.plus(baseIndent) } - return offset + return baseIndent } override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = parentBlock?.let { parent -> - isFirstChildConditionLoopDirective() || - ( - ( - parent is SqlValuesGroupBlock || - parent is SqlElConditionLoopCommentBlock - ) && - parent.childBlocks.dropLast(1).isEmpty() - ) + parent is SqlValuesGroupBlock && + parent.childBlocks.dropLast(1).isEmpty() } == true || !isFirstTable } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithQueryGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithQueryGroupBlock.kt index db99b751..1ae622ab 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithQueryGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithQueryGroupBlock.kt @@ -49,12 +49,7 @@ class SqlWithQueryGroupBlock( override fun createBlockIndentLen(): Int = 0 override fun createGroupIndentLen(): Int { - val sumChildren = - if (isConditionLoopDirectiveRegisteredBeforeParent()) { - childBlocks.drop(1) - } else { - childBlocks - } + val sumChildren = childBlocks return sumChildren .sumOf { it.getNodeText().length.plus(1) } .plus(getNodeText().length) diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithQuerySubGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithQuerySubGroupBlock.kt index 589e6e90..f2213659 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithQuerySubGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/with/SqlWithQuerySubGroupBlock.kt @@ -31,10 +31,11 @@ class SqlWithQuerySubGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } + fun parentInlineDirective(): Boolean = parentBlock?.conditionLoopDirective != null + override fun createBlockIndentLen(): Int = offset override fun createGroupIndentLen(): Int = offset diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/condition/SqlConditionalExpressionGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlConditionalExpressionGroupBlock.kt similarity index 62% rename from src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/condition/SqlConditionalExpressionGroupBlock.kt rename to src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlConditionalExpressionGroupBlock.kt index 9a95441f..59054b4d 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/condition/SqlConditionalExpressionGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlConditionalExpressionGroupBlock.kt @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.formatter.block.group.keyword.condition +package org.domaframework.doma.intellij.formatter.block.group.subgroup import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.keyword.condition.SqlConditionKeywordGroupBlock import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext /** @@ -36,7 +35,6 @@ class SqlConditionalExpressionGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -48,24 +46,8 @@ class SqlConditionalExpressionGroupBlock( override fun createBlockIndentLen(): Int = parentBlock?.let { parent -> - if (parent is SqlElConditionLoopCommentBlock) { - val groupIndentLen = parent.indent.groupIndentLen - val grand = parent.parentBlock - val directiveParentTextLen = - if (grand !is SqlElConditionLoopCommentBlock) { - grand - ?.getNodeText() - ?.length - ?.plus(1) ?: 0 - } else { - 0 - } - groupIndentLen + directiveParentTextLen - } else { - calculatePrevBlocksLength(prevBlocks, parent).plus(1) - } - } - ?: offset + calculatePrevBlocksLength(prevBlocks, parent).plus(1) + } ?: offset override fun createGroupIndentLen(): Int = indent.indentLen.plus(1) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlFunctionParamBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlFunctionParamBlock.kt index e5fa7583..70f6659a 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlFunctionParamBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlFunctionParamBlock.kt @@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.formatter.block.group.subgroup import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlDefaultCommentBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.expr.SqlElAtSignBlock import org.domaframework.doma.intellij.formatter.block.expr.SqlElSymbolBlock import org.domaframework.doma.intellij.formatter.block.other.SqlOtherBlock @@ -44,7 +43,6 @@ class SqlFunctionParamBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.PARAM - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -54,9 +52,6 @@ class SqlFunctionParamBlock( override fun createBlockIndentLen(): Int { parentBlock?.let { parent -> - - if (parent is SqlElConditionLoopCommentBlock) return parent.indent.groupIndentLen - if (parent !is SqlSubGroupBlock) { return if (parent is SqlFunctionGroupBlock) { parent.indent.groupIndentLen @@ -89,13 +84,7 @@ class SqlFunctionParamBlock( it.node.elementType != SqlTypes.DOT } ?: emptyList() - val parentText = - if (isParentConditionLoopDirective()) { - val grand = parentBlock?.parentBlock - grand?.getNodeText() ?: "" - } else { - "" - } + val prevLength = prevChildrenDropLast .sumOf { @@ -106,7 +95,7 @@ class SqlFunctionParamBlock( val consecutiveSymbolCount = calculateConsecutiveSymbolCount(prevChildrenDropLast) val spaces = prevChildrenDropLast.count().minus(consecutiveSymbolCount) - return prevLength.plus(spaces).plus(parentText.length).plus(parentGroupIndent) + return prevLength.plus(spaces).plus(parentGroupIndent) } private fun calculateConsecutiveSymbolCount(prevChildrenDropLast: List): Int { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlSubGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlSubGroupBlock.kt index 87698059..71454519 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlSubGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlSubGroupBlock.kt @@ -23,7 +23,6 @@ import org.domaframework.doma.intellij.common.util.TypeUtil import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.SqlRightPatternBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlCommentBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.conflict.SqlDoGroupBlock import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateViewGroupBlock @@ -51,14 +50,13 @@ abstract class SqlSubGroupBlock( SqlWithCommonTableGroupBlock::class, SqlWithColumnGroupBlock::class, SqlCreateViewGroupBlock::class, - SqlElConditionLoopCommentBlock::class, ) } - open val offset = 1 + override val offset = 1 - // TODO Even if the first element of a subgroup is a comment, - // the indentation of subsequent elements is now aligned. + // Even if the first element of a subgroup is a comment, + // the indentation of subsequent elements is now aligned. var isFirstLineComment = false var prevChildren: List? = emptyList() var endPatternBlock: SqlRightPatternBlock? = null @@ -74,7 +72,6 @@ abstract class SqlSubGroupBlock( super.setParentGroupBlock(lastGroup) prevChildren = parentBlock?.childBlocks?.toList() indent.indentLevel = indent.indentLevel - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -102,12 +99,7 @@ abstract class SqlSubGroupBlock( override fun isLeaf(): Boolean = true - override fun createBlockIndentLen(): Int { - parentBlock?.let { parent -> - if (parent is SqlElConditionLoopCommentBlock) return parent.indent.groupIndentLen - } - return offset - } + override fun createBlockIndentLen(): Int = offset override fun createGroupIndentLen(): Int = parentBlock?.let { parent -> @@ -118,23 +110,7 @@ abstract class SqlSubGroupBlock( lastGroup?.let { lastBlock -> if (lastBlock is SqlJoinQueriesGroupBlock) return true if (lastGroup is SqlInGroupBlock) return false - if (lastGroup is SqlElConditionLoopCommentBlock) { - return lastGroup.checkConditionLoopDirectiveParentBlock(this) || - lastGroup.conditionType.isElse() - } - val grand = lastBlock.parentBlock - if (grand is SqlElConditionLoopCommentBlock) { - if (grand.conditionType.isElse()) { - return false - } - } - val lastParent = lastBlock.parentBlock - val expectedParent = - if (lastParent is SqlElConditionLoopCommentBlock) { - lastParent.parentBlock?.parentBlock - } else { - lastBlock.parentBlock - } + val expectedParent = lastBlock.parentBlock return TypeUtil.isExpectedClassType(NEW_LINE_EXPECTED_TYPES, expectedParent) } return false diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlSubQueryGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlSubQueryGroupBlock.kt index 7cc61e03..b2c098f0 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlSubQueryGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/subgroup/SqlSubQueryGroupBlock.kt @@ -19,10 +19,8 @@ import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlDefaultCommentBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlJoinGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.condition.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.top.SqlJoinQueriesGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithCommonTableGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithQuerySubGroupBlock @@ -37,7 +35,6 @@ open class SqlSubQueryGroupBlock( ) { override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -52,16 +49,6 @@ open class SqlSubQueryGroupBlock( override fun createBlockIndentLen(): Int = parentBlock?.let { parent -> return when (parent) { - is SqlElConditionLoopCommentBlock -> { - return if (parent.isBeforeParentBlock()) { - parent.parentBlock - ?.indent - ?.groupIndentLen - ?.plus(1) ?: 1 - } else { - parent.indent.indentLen - } - } is SqlWithQuerySubGroupBlock -> return parent.indent.groupIndentLen is SqlJoinQueriesGroupBlock -> return parent.indent.indentLen is SqlJoinGroupBlock -> return parent.indent.groupIndentLen.plus(1) @@ -69,12 +56,7 @@ open class SqlSubQueryGroupBlock( val children = prevChildren?.filter { shouldIncludeChildBlock(it, parent) }?.dropLast(1) // Retrieve the list of child blocks excluding the conditional directive that appears immediately before this block, // as it is already included as a child block. - val sumChildren = - if (children?.firstOrNull() is SqlElConditionLoopCommentBlock) { - children.drop(1) - } else { - children ?: emptyList() - } + val sumChildren = children ?: emptyList() return sumChildren .sumOf { prev -> prev diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/other/SqlEscapeBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/other/SqlEscapeBlock.kt index f687a606..77ea2f43 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/other/SqlEscapeBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/other/SqlEscapeBlock.kt @@ -17,7 +17,6 @@ package org.domaframework.doma.intellij.formatter.block.other import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlArrayListGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubQueryGroupBlock import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext @@ -36,13 +35,7 @@ class SqlEscapeBlock( } override fun createBlockIndentLen(): Int { - val parentEscapeBlock = - if (isParentConditionLoopDirective()) { - if (parentBlock?.parentBlock is SqlEscapeBlock)1 else 0 - } else { - 0 - } - val prevBlocks = parentBlock?.childBlocks?.count { it is SqlEscapeBlock }?.plus(parentEscapeBlock) ?: 0 + val prevBlocks = parentBlock?.childBlocks?.count { it is SqlEscapeBlock } ?: 0 val hasEvenEscapeBlocks = prevBlocks.let { it % 2 == 0 } == true isEndEscape = hasEvenEscapeBlocks || getNodeText() == "]" @@ -66,12 +59,8 @@ class SqlEscapeBlock( return parentIndentLen.plus(1) } - is SqlElConditionLoopCommentBlock -> { - return parent.indent.groupIndentLen - } - else -> { - if (isSaveSpace(parentBlock))return parentBlock?.indent?.groupIndentLen ?: 1 + if (isSaveSpace(parentBlock) || conditionLoopDirective != null)return parentBlock?.indent?.groupIndentLen ?: 1 return 1 } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/other/SqlOtherBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/other/SqlOtherBlock.kt index cc8eff48..caae824a 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/other/SqlOtherBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/other/SqlOtherBlock.kt @@ -42,7 +42,6 @@ open class SqlOtherBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.NONE - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlArrayWordBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlArrayWordBlock.kt index f90ed64b..c51da7bd 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlArrayWordBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlArrayWordBlock.kt @@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.formatter.block.word import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.expr.SqlElDotBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlArrayListGroupBlock import org.domaframework.doma.intellij.formatter.block.other.SqlOtherBlock @@ -48,11 +47,7 @@ open class SqlArrayWordBlock( override fun buildChildren(): MutableList = mutableListOf() - override fun createBlockIndentLen(): Int = - when (val parent = parentBlock) { - is SqlElConditionLoopCommentBlock -> parent.indent.groupIndentLen - else -> 1 - } + override fun createBlockIndentLen(): Int = 1 override fun createGroupIndentLen(): Int = parentBlock diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlFunctionGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlFunctionGroupBlock.kt index a73fae12..8c8b86c9 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlFunctionGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlFunctionGroupBlock.kt @@ -18,12 +18,9 @@ package org.domaframework.doma.intellij.formatter.block.word import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlDefaultCommentBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlFunctionParamBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext -import kotlin.collections.emptyList -import kotlin.collections.toList class SqlFunctionGroupBlock( node: ASTNode, @@ -35,7 +32,6 @@ class SqlFunctionGroupBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) prevChildren = lastGroup?.childBlocks?.toList() ?: emptyList() - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = createGroupIndentLen() } @@ -59,12 +55,6 @@ class SqlFunctionGroupBlock( is SqlSubGroupBlock -> prevBlocksLength - is SqlElConditionLoopCommentBlock -> { - val directiveParent = parentBlock?.parentBlock - val directiveParentLen = directiveParent?.getNodeText()?.length?.plus(1) ?: 1 - prevBlocksLength.plus(directiveParentLen) - } - else -> prevBlocksLength.plus(1) } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlWordBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlWordBlock.kt index 5cf11e1b..8c5ae831 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlWordBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/word/SqlWordBlock.kt @@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.formatter.block.word import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.formatter.block.SqlBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithCommonTableGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubQueryGroupBlock import org.domaframework.doma.intellij.formatter.util.IndentType @@ -44,7 +43,6 @@ open class SqlWordBlock( override fun setParentGroupBlock(lastGroup: SqlBlock?) { super.setParentGroupBlock(lastGroup) - indent.indentLen = createBlockIndentLen() indent.groupIndentLen = indent.indentLen } @@ -59,6 +57,7 @@ open class SqlWordBlock( override fun createBlockIndentLen(): Int { parentBlock?.let { parent -> when (parent) { + // Calculate indentation assuming function parameters or within a list. is SqlSubQueryGroupBlock -> { val parentIndentLen = parent.indent.groupIndentLen val grand = parent.parentBlock @@ -69,10 +68,6 @@ open class SqlWordBlock( return parentIndentLen.plus(1) } - is SqlElConditionLoopCommentBlock -> { - return parent.indent.groupIndentLen - } - else -> { return parent.indent.groupIndentLen.plus(1) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/builder/SqlBlockBuilder.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/builder/SqlBlockBuilder.kt index 2ac198bd..cfa84644 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/builder/SqlBlockBuilder.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/builder/SqlBlockBuilder.kt @@ -15,31 +15,47 @@ */ package org.domaframework.doma.intellij.formatter.builder -import org.domaframework.doma.intellij.common.util.TypeUtil.isExpectedClassType import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlDefaultCommentBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGroupBlock open class SqlBlockBuilder { - private val updateDirectiveParentTypes = - listOf( - SqlDefaultCommentBlock::class, - ) - - private val originalConditionLoopDirectiveParentType = - listOf( - SqlKeywordGroupBlock::class, - SqlSubGroupBlock::class, - ) - private val groupTopNodeIndexHistory = mutableListOf() private val commentBlocks = mutableListOf() + // The list that manages conditional loop directive blocks. private val conditionOrLoopBlocks = mutableListOf() + fun getLastConditionOrLoopBlock() = conditionOrLoopBlocks.lastOrNull() + + fun getFirstConditionOrLoopBlock() = conditionOrLoopBlocks.firstOrNull() + + /** + * Get directives that don't have dependencies yet + */ + fun getLastNotDependOnConditionOrLoopBlock() = conditionOrLoopBlocks.findLast { it.getDependsOnBlock() == null } + + fun getLastOpenDependOnConditionOrLoopBlock() = conditionOrLoopBlocks.findLast { it.conditionEnd == null } + + fun removeGroupForClosedDirective() { + if (groupTopNodeIndexHistory.isEmpty()) return + val lastCloseDirective = conditionOrLoopBlocks.lastOrNull() + val dependBlock = lastCloseDirective?.getDependsOnBlock() + if (dependBlock != null) { + val removeCount = + groupTopNodeIndexHistory.takeLastWhile { it.node.startOffset >= dependBlock.node.startOffset } + val startIndex = groupTopNodeIndexHistory.size - removeCount.size + if (startIndex >= 0) { + clearSubListGroupTopNodeIndexHistory(startIndex) + } + } + // Also remove condition/loop directives associated with 'end' or `else` from the list + removeConditionOrLoopBlockLast() + } + + fun getNotClosedConditionOrLoopBlock() = conditionOrLoopBlocks.filter { it.conditionEnd == null } + fun getGroupTopNodeIndexHistory(): List = groupTopNodeIndexHistory fun getLastGroupFilterDirective(): SqlBlock? = getGroupTopNodeIndexHistory().lastOrNull { it !is SqlElConditionLoopCommentBlock } @@ -71,72 +87,49 @@ open class SqlBlockBuilder { } } - /** - * For condition/loop directive blocks - * determine the parent based on the type of block immediately below. - * - * When this process is invoked, a directive block has already been added to [groupTopNodeIndexHistory], - * and the parent of the block passed as [nextBlock] has already been determined. - */ - fun updateConditionLoopBlockIndent(nextBlock: SqlBlock) { - if (!isExpectedClassType(updateDirectiveParentTypes, nextBlock)) { - if (conditionOrLoopBlocks.isNotEmpty()) { - val lastGroup = groupTopNodeIndexHistory.lastOrNull() - conditionOrLoopBlocks - .filter { it.parentBlock == null } - .forEach { block -> - var setParentBlock: SqlBlock? = null - val conditionBlockIndex = groupTopNodeIndexHistory.indexOf(block) - val prevConditionBlockGroup = - if (conditionBlockIndex > 0) { - groupTopNodeIndexHistory[conditionBlockIndex - 1] - } else { - null - } - - if (lastGroup == nextBlock) { - setParentBlock = - if (isExpectedClassType( - originalConditionLoopDirectiveParentType, - nextBlock, - ) - ) { - nextBlock - } else { - null - } - } else { - setParentBlock = - if (isExpectedClassType( - originalConditionLoopDirectiveParentType, - nextBlock, - ) - ) { - nextBlock - } else { - prevConditionBlockGroup - } - } - - if (block != nextBlock) { - block.setParentGroupBlock(setParentBlock) - } else if (setParentBlock is SqlElConditionLoopCommentBlock) { - block.setParentGroupBlock(setParentBlock) - } - } - } - } - } - + @Suppress("ktlint:standard:no-consecutive-comments") fun getLastGroupTopNodeIndexHistory(): SqlBlock? = groupTopNodeIndexHistory.lastOrNull() fun removeLastGroupTopNodeIndexHistory() { if (groupTopNodeIndexHistory.isNotEmpty()) { + val openDirective = getLastOpenDependOnConditionOrLoopBlock() + openDirective?.let { directive -> + val removeBlock = groupTopNodeIndexHistory.last() + if (removeBlock.node.startOffset > directive.node.startOffset) { + groupTopNodeIndexHistory.removeLast() + } + return + } groupTopNodeIndexHistory.removeLast() } } - fun clearSubListGroupTopNodeIndexHistory(start: Int) { + /** + * When deleting group list, prevent deletion from outside condition/loop directives to inside condition/loop directives + */ + fun clearSubListGroupTopNodeIndexHistory(startIndex: Int) { + val openDirective = getLastOpenDependOnConditionOrLoopBlock() + openDirective?.let { directive -> + val removeList = + groupTopNodeIndexHistory + .subList( + startIndex, + groupTopNodeIndexHistory.size, + ) + // Also exclude blocks before the first condition/loop directive in conditionOrLoopBlocks + val firstConditionLoopCommentBlock = conditionOrLoopBlocks.firstOrNull() + val inlineDirectiveList = + removeList.filter { + it.node.startOffset > directive.node.startOffset || + it.node.startOffset < (firstConditionLoopCommentBlock?.node?.startOffset ?: 0) + } + inlineDirectiveList.forEach { groupTopNodeIndexHistory.remove(it) } + return + } + clearGroupList(startIndex) + } + + private fun clearGroupList(start: Int) { groupTopNodeIndexHistory .subList( start, diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/builder/SqlBlockRelationBuilder.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/builder/SqlBlockRelationBuilder.kt index e66f1006..b4957a2a 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/builder/SqlBlockRelationBuilder.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/builder/SqlBlockRelationBuilder.kt @@ -19,12 +19,14 @@ import org.domaframework.doma.intellij.common.util.TypeUtil import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.SqlKeywordBlock import org.domaframework.doma.intellij.formatter.block.SqlRightPatternBlock +import org.domaframework.doma.intellij.formatter.block.comma.SqlCommaBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlDefaultCommentBlock import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.conflict.SqlDoGroupBlock import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnDefinitionRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnRawGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.column.SqlRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateViewGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineGroupBlock @@ -34,7 +36,6 @@ import org.domaframework.doma.intellij.formatter.block.group.keyword.option.SqlI import org.domaframework.doma.intellij.formatter.block.group.keyword.option.SqlLateralGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlReturningGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlTableModifySecondGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.top.SqlTableModificationKeyword import org.domaframework.doma.intellij.formatter.block.group.keyword.top.SqlTopQueryGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlUpdateQueryGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithCommonTableGroupBlock @@ -88,33 +89,11 @@ class SqlBlockRelationBuilder( childBlock, blockBuilder, ) - val lastGroup = blockBuilder.getLastGroupTopNodeIndexHistory() - if (lastGroup is SqlElConditionLoopCommentBlock) { - updateParentGroupLastConditionLoop(lastGroup, context, false) { block -> - block.indent.indentLevel < childBlock.indent.indentLevel || - block is SqlNewGroupBlock - } - return - } setParentGroups(context) { history -> return@setParentGroups history.lastOrNull() } } - /** - * Does not set a parent. - */ - fun updateGroupBlockAddGroup(childBlock: SqlBlock) { - setParentGroups( - SetParentContext( - childBlock, - blockBuilder, - ), - ) { history -> - return@setParentGroups null - } - } - /** * Registers itself as a child element in the same block as the parent of the last group at the time of processing. */ @@ -138,53 +117,12 @@ class SqlBlockRelationBuilder( childBlock: SqlKeywordGroupBlock, ) { val context = SetParentContext(childBlock, blockBuilder) - if (lastGroupBlock is SqlElConditionLoopCommentBlock) { - if (childBlock is SqlTableModificationKeyword) { - handleConditionLoopParentForTableModification(lastGroupBlock, context, childBlock) - } else { - handleConditionLoopParent(lastGroupBlock, context, childBlock) - } - return - } if (childBlock.indent.indentLevel == IndentType.TOP) { handleTopLevelKeyword(lastGroupBlock, childBlock, context) return } - if (lastGroupBlock !is SqlSubGroupBlock) { - if (lastIndentLevel > childBlock.indent.indentLevel) { - val findLastGroup = - blockBuilder.getGroupTopNodeIndexHistory().findLast { - it.indent.indentLevel < childBlock.indent.indentLevel || - it is - SqlElConditionLoopCommentBlock - } - if (findLastGroup is SqlElConditionLoopCommentBlock) { - handleConditionLoopParent(findLastGroup, context, childBlock) - return - } - } - } - handleNonTopLevelKeyword(lastGroupBlock, lastIndentLevel, childBlock, context) - } - - private fun handleConditionLoopParent( - lastGroupBlock: SqlElConditionLoopCommentBlock, - context: SetParentContext, - childBlock: SqlKeywordGroupBlock, - ) { - updateParentGroupLastConditionLoop(lastGroupBlock, context, true) { - it.indent.indentLevel < childBlock.indent.indentLevel - } - } - private fun handleConditionLoopParentForTableModification( - lastGroupBlock: SqlElConditionLoopCommentBlock, - context: SetParentContext, - childBlock: SqlKeywordGroupBlock, - ) { - updateParentGroupLastConditionLoop(lastGroupBlock, context) { - it.indent.indentLevel <= childBlock.indent.indentLevel - } + handleNonTopLevelKeyword(lastGroupBlock, lastIndentLevel, childBlock, context) } private fun handleTopLevelKeyword( @@ -203,6 +141,9 @@ class SqlBlockRelationBuilder( setParentGroups(context) { return@setParentGroups parentBlock } } + /** + * Search for groups before the top-level keyword, select the parent, and swap the list + */ private fun findTopLevelParent(): SqlBlock? { val topKeywordIndex = blockBuilder.getGroupTopNodeIndex { @@ -213,19 +154,24 @@ class SqlBlockRelationBuilder( it is SqlSubGroupBlock } + // Determine the parent block based on the order of appearance of top-level keywords or subqueries val (parentBlock, deleteIndex) = when { + // If only a top-level keyword is found, get the same parent as it topKeywordIndex >= 0 && subGroupIndex < 0 -> { val block = blockBuilder.getGroupTopNodeIndexHistory()[topKeywordIndex] block.parentBlock to topKeywordIndex } + // If a top-level keyword is found before a subquery, make the subquery group the parent topKeywordIndex > subGroupIndex -> { val block = blockBuilder.getGroupTopNodeIndexHistory()[subGroupIndex] block to topKeywordIndex } + // If neither a subquery nor a top-level keyword is found, don't set a parent else -> null to -1 } + // Remove top-level keywords from the group list if (deleteIndex >= 0) { blockBuilder.clearSubListGroupTopNodeIndexHistory(deleteIndex) } @@ -385,13 +331,6 @@ class SqlBlockRelationBuilder( blockBuilder, ) - if (lastGroupBlock is SqlElConditionLoopCommentBlock) { - updateParentGroupLastConditionLoop(lastGroupBlock, context) { - it.indent.indentLevel < childBlock.indent.indentLevel - } - return - } - if (TypeUtil.isExpectedClassType(COLUMN_RAW_EXPECTED_TYPES, lastGroupBlock)) { blockBuilder.removeLastGroupTopNodeIndexHistory() } @@ -423,14 +362,6 @@ class SqlBlockRelationBuilder( return } - val lastGroupBlock = blockBuilder.getLastGroupTopNodeIndexHistory() - if (lastGroupBlock is SqlElConditionLoopCommentBlock) { - updateParentGroupLastConditionLoop(lastGroupBlock, context) { - it.indent.indentLevel == IndentType.INLINE - } - return - } - val caseBlockIndex = blockBuilder.getGroupTopNodeIndex { block -> block.indent.indentLevel == IndentType.INLINE @@ -454,54 +385,9 @@ class SqlBlockRelationBuilder( ) } - /** - * Updates the parent of the last conditional directive block and sets the parent of the current block. - */ - private fun updateParentGroupLastConditionLoop( - lastGroupBlock: SqlElConditionLoopCommentBlock, - context: SetParentContext, - findSubGroup: Boolean = false, - findDefaultParent: (SqlBlock) -> Boolean, - ) { - if (lastGroupBlock.parentBlock != null) { - setParentGroups(context) { lastGroupBlock } - return - } - - val findParent = findParentForConditionLoop(findDefaultParent, findSubGroup) - handleConditionLoopParentAssignment(lastGroupBlock, context, findParent) - } - - private fun findParentForConditionLoop( - findDefaultParent: (SqlBlock) -> Boolean, - findSubGroup: Boolean = false, - ): SqlBlock? = - blockBuilder.getGroupTopNodeIndexHistory().lastOrNull { block -> - findDefaultParent(block) || - findSubGroup && block is SqlSubGroupBlock || - (block is SqlElConditionLoopCommentBlock && block.parentBlock != null) - } - - private fun handleConditionLoopParentAssignment( - lastGroupBlock: SqlElConditionLoopCommentBlock, - context: SetParentContext, - findParent: SqlBlock?, - ) { - when (findParent) { - is SqlElConditionLoopCommentBlock -> { - lastGroupBlock.setParentGroupBlock(findParent) - setParentGroups(context) { lastGroupBlock } - } - else -> { - setParentGroups(context) { findParent } - lastGroupBlock.setParentGroupBlock(context.childBlock) - } - } - } - - fun updateConditionLoopCommentBlockParent( - lastGroupBlock: SqlBlock, - childBlock: SqlElConditionLoopCommentBlock, + fun updateSqlBlockAndOverIndentLevel( + childBlock: SqlCommaBlock, + findSubQuery: Boolean = false, ) { val context = SetParentContext( @@ -509,35 +395,10 @@ class SqlBlockRelationBuilder( blockBuilder, ) setParentGroups(context) { history -> - if (childBlock.conditionType.isEnd() || childBlock.conditionType.isElse()) { - // remove self and previous conditional directive block - blockBuilder.removeConditionOrLoopBlockLast() - blockBuilder.removeConditionOrLoopBlockLast() - - val directiveIndex = - blockBuilder - .getGroupTopNodeIndex { it is SqlElConditionLoopCommentBlock && it != childBlock } - if (directiveIndex >= 0) { - val lastConditionLoopCommentBlock = - blockBuilder.getGroupTopNodeIndexHistory()[directiveIndex] - blockBuilder.clearSubListGroupTopNodeIndexHistory(directiveIndex) - return@setParentGroups lastConditionLoopCommentBlock - } - return@setParentGroups null - } - - // If the most recent block is a conditional directive, set it as the parent block. - if (lastGroupBlock is SqlElConditionLoopCommentBlock) { - val prevGroupIndex = blockBuilder.getGroupTopNodeIndex { it == lastGroupBlock } - if (prevGroupIndex > 0 && lastGroupBlock.parentBlock == null) { - // Determine the parent of the most recent conditional directive. - val prevGroup = blockBuilder.getGroupTopNodeIndexHistory()[prevGroupIndex - 1] - lastGroupBlock.setParentGroupBlock(prevGroup) - } - return@setParentGroups lastGroupBlock + return@setParentGroups history.findLast { + it.indent.indentLevel < childBlock.indent.indentLevel || + (findSubQuery && it is SqlSubGroupBlock) } - // Temporary Parent Block - return@setParentGroups history.lastOrNull() } } @@ -609,7 +470,8 @@ class SqlBlockRelationBuilder( } /** - * Determines its parent group and, if conditions are met, registers itself as a new group block in the list. + * Determines its parent group and, if conditions are met, + * registers itself as a new group block in the list. */ private fun setParentGroups( context: SetParentContext, @@ -620,60 +482,148 @@ class SqlBlockRelationBuilder( context.blockBuilder.getGroupTopNodeIndexHistory() as MutableList, ) val targetChildBlock = context.childBlock - - if (shouldSkipParentSetting(targetChildBlock)) return - - assignParentGroup(targetChildBlock, parentGroup) - registerAsNewGroupIfNeeded(targetChildBlock, context.blockBuilder) - updateBlockIndents(targetChildBlock, context.blockBuilder) + if (targetChildBlock is SqlDefaultCommentBlock) return + + // If a value can be retrieved from the condition/loop directive list, + // first calculate the original indent of the current block + val dependDirective = blockBuilder.getLastConditionOrLoopBlock() + if (targetChildBlock !is SqlElConditionLoopCommentBlock) { + setParentNonLoopConditionDirective( + context, + targetChildBlock, + parentGroup, + dependDirective, + ) + } else { + val nestParentBlock = blockBuilder.getLastConditionOrLoopBlock() + targetChildBlock.nestParentBlock = nestParentBlock + setParentLoopConditionDirective( + targetChildBlock, + parentGroup, + dependDirective, + ) + } + context.blockBuilder.updateCommentBlockIndent(targetChildBlock) } - private fun shouldSkipParentSetting(block: SqlBlock) = block is SqlDefaultCommentBlock - - private fun assignParentGroup( + /** + * Set parent-child relationships for non-condition/loop directives + */ + private fun setParentNonLoopConditionDirective( + context: SetParentContext, targetChildBlock: SqlBlock, parentGroup: SqlBlock?, + dependDirective: SqlElConditionLoopCommentBlock?, ) { - when { - isStartDirectiveConditionLoop(targetChildBlock) -> { - val conditionLoop = targetChildBlock as SqlElConditionLoopCommentBlock - conditionLoop.tempParentBlock = parentGroup - if (shouldSetParentImmediately(parentGroup)) { - conditionLoop.setParentGroupBlock(parentGroup) + // If the child block is at the same level as the previous block, + // the condition/loop directive makes the upper block that was retained its parent + val lastGroup = blockBuilder.getLastGroupTopNodeIndexHistory() + val lastGroupLevel = lastGroup?.indent?.indentLevel ?: IndentType.FILE + val inlineDirective = lastGroupLevel >= targetChildBlock.indent.indentLevel && dependDirective?.nestParentBlock != null + if (inlineDirective) { + dependDirective.setParentSelfNestBlock() + } + + // If dependDirective has a parent set (nested), align the indent to dependDirective + // If dependDirective doesn't have a parent set, align dependDirective to its own indent + val lastParentChild = parentGroup?.childBlocks?.lastOrNull() + targetChildBlock.setParentGroupBlock(parentGroup) + if (dependDirective != null) { + targetChildBlock.createBlockIndentLenDirective(parentGroup, dependDirective) + } + // Within condition/loop directives, if there is a parent condition/loop directive but the parent's dependency is different from targetChildBlock's parent, + // release the parent condition/loop directive and perform normal condition/loop directive association + val dependDirectiveParent = dependDirective?.parentBlock + // If targetChildBlock is a group block and the last group block differs from parentGroup, + // reset the parent-child relationship of the previous condition/loop directive and start a new nest + var recalculate = false + if (parentGroup != lastGroup) { + if (targetChildBlock !is SqlRawGroupBlock) { + if (targetChildBlock !is SqlNewGroupBlock && + dependDirectiveParent is SqlElConditionLoopCommentBlock + ) { + dependDirective.parentBlock = null + recalculate = true + } else { + lastParentChild?.let { last -> + // Judge by whether the parent's last child is at the same indent level as yourself? + if (last.indent.indentLevel > targetChildBlock.indent.indentLevel) { + dependDirective?.parentBlock = null + recalculate = true + } + } + } + } + } else { + val firstConditionLoopCommentBlock = blockBuilder.getFirstConditionOrLoopBlock() + if (lastParentChild != null && firstConditionLoopCommentBlock != null && + firstConditionLoopCommentBlock.conditionType.isStartDirective() + ) { + recalculate = lastParentChild.node.startOffset < firstConditionLoopCommentBlock.node.startOffset && + targetChildBlock is SqlNewGroupBlock + } + if (!recalculate && targetChildBlock is SqlWithCommonTableGroupBlock) { + val tmpParentDirective = dependDirective?.nestParentBlock + val tempParentDependBlock = tmpParentDirective?.getDependsOnBlock() + if (tempParentDependBlock != null && firstConditionLoopCommentBlock != null && + lastParentChild is SqlWithCommonTableGroupBlock + ) { + dependDirective.setParentSelfNestBlock() + recalculate = + tempParentDependBlock.indent.indentLevel >= targetChildBlock.indent.indentLevel } } - else -> targetChildBlock.setParentGroupBlock(parentGroup) } - } - - private fun isStartDirectiveConditionLoop(block: SqlBlock) = - block is SqlElConditionLoopCommentBlock && block.conditionType.isStartDirective() - - private fun shouldSetParentImmediately(parentGroup: SqlBlock?) = - (parentGroup is SqlElConditionLoopCommentBlock || parentGroup is SqlSubGroupBlock) && - parentGroup.parentBlock != null + // If the previous group is lower than your own group level, trace back the directive to yourself as the start of a new group, + // and recalculate the indent from the top of the nest to match your parent block + if (recalculate) { + if (dependDirective?.conditionType?.isStartDirective() == true) { + targetChildBlock.recalculateDirectiveIndent() + } + } - private fun registerAsNewGroupIfNeeded( - targetChildBlock: SqlBlock, - blockBuilder: SqlBlockBuilder, - ) { - if (shouldRegisterAsNewGroup(targetChildBlock, blockBuilder)) { - blockBuilder.addGroupTopNodeIndexHistory(targetChildBlock) + // If a value is retrieved from the conditional/loop directive list, + // set the current block as the dependency target for the directive. + if (isNewGroup(targetChildBlock, context.blockBuilder) || + TypeUtil.isExpectedClassType(NEW_GROUP_EXPECTED_TYPES, targetChildBlock) + ) { + context.blockBuilder.addGroupTopNodeIndexHistory(targetChildBlock) } } - private fun shouldRegisterAsNewGroup( - block: SqlBlock, - blockBuilder: SqlBlockBuilder, - ) = isNewGroup(block, blockBuilder) || - TypeUtil.isExpectedClassType(NEW_GROUP_EXPECTED_TYPES, block) - - private fun updateBlockIndents( - targetChildBlock: SqlBlock, - blockBuilder: SqlBlockBuilder, + private fun setParentLoopConditionDirective( + targetChildBlock: SqlElConditionLoopCommentBlock, + parentGroup: SqlBlock?, + dependDirective: SqlElConditionLoopCommentBlock?, ) { - blockBuilder.updateCommentBlockIndent(targetChildBlock) - blockBuilder.updateConditionLoopBlockIndent(targetChildBlock) + // For else and end directives, make the start directive in the list the parent. The dependency is set later + if (!targetChildBlock.conditionType.isStartDirective()) { + targetChildBlock.setParentGroupBlock(dependDirective) + } else { + // If the subgroup block is parentGroup, make it the direct parent + if (parentGroup is SqlSubGroupBlock && dependDirective?.parentBlock != parentGroup) { + targetChildBlock.setParentGroupBlock(parentGroup) + return + } + // If the child is also a condition/loop directive, + // calculate the indent of the previous directive according to the previous group block + if (dependDirective != null) { + val parentDepend = dependDirective.getDependsOnBlock() + if (parentDepend == null) { + dependDirective.setParentGroupBlock(parentGroup) + targetChildBlock.setParentGroupBlock(dependDirective, blockBuilder) + } else { + // Also set the parent of itself with the previous directive and calculate the indent + if (parentGroup !is SqlNewGroupBlock || ( + parentDepend !is SqlNewGroupBlock && + parentDepend.node.startOffset >= parentGroup.node.startOffset + ) + ) { + targetChildBlock.setParentGroupBlock(dependDirective, blockBuilder) + } + } + } + } } /** @@ -683,18 +633,10 @@ class SqlBlockRelationBuilder( childBlock: SqlBlock, blockBuilder: SqlBlockBuilder, ): Boolean { - if (isConditionLoopNewGroup(childBlock)) { - return true - } - val lastGroup = blockBuilder.getLastGroupTopNodeIndexHistory() return isNewGroupAndNotSetLineKeywords(childBlock, lastGroup) } - private fun isConditionLoopNewGroup(childBlock: SqlBlock): Boolean = - childBlock is SqlElConditionLoopCommentBlock && - (childBlock.conditionType.isStartDirective() || childBlock.conditionType.isElse()) - fun isNewGroupAndNotSetLineKeywords( childBlock: SqlBlock, lastGroup: SqlBlock?, diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/handler/CommaRawClauseHandler.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/handler/CommaRawClauseHandler.kt index dfad48c4..416a5c95 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/handler/CommaRawClauseHandler.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/handler/CommaRawClauseHandler.kt @@ -19,7 +19,6 @@ import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.comma.SqlArrayCommaBlock import org.domaframework.doma.intellij.formatter.block.comma.SqlCommaBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithCommonTableGroupBlock @@ -36,30 +35,7 @@ object CommaRawClauseHandler { lastGroup: SqlBlock?, child: ASTNode, sqlBlockFormattingCtx: SqlBlockFormattingContext, - ): SqlBlock = - when (lastGroup) { - is SqlElConditionLoopCommentBlock -> - createCommaBlockForConditionLoop( - lastGroup, - child, - sqlBlockFormattingCtx, - ) - - else -> createCommaBlockForGroup(lastGroup, child, sqlBlockFormattingCtx) - } - - /** - * Creates a comma block for condition/loop comment blocks. - * Uses the parent block if available, otherwise uses the temporary parent block. - */ - private fun createCommaBlockForConditionLoop( - lastGroup: SqlElConditionLoopCommentBlock, - child: ASTNode, - sqlBlockFormattingCtx: SqlBlockFormattingContext, - ): SqlBlock { - val effectiveParent = lastGroup.parentBlock ?: lastGroup.tempParentBlock - return createCommaBlockForGroup(effectiveParent, child, sqlBlockFormattingCtx) - } + ): SqlBlock = createCommaBlockForGroup(lastGroup, child, sqlBlockFormattingCtx) /** * Creates an appropriate comma block based on the group type and indent level. diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/handler/NotQueryGroupHandler.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/handler/NotQueryGroupHandler.kt index 9188d0ee..a66c2178 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/handler/NotQueryGroupHandler.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/handler/NotQueryGroupHandler.kt @@ -18,15 +18,14 @@ package org.domaframework.doma.intellij.formatter.handler import com.intellij.lang.ASTNode import org.domaframework.doma.intellij.formatter.block.SqlBlock import org.domaframework.doma.intellij.formatter.block.comma.SqlCommaBlock -import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.conflict.SqlConflictClauseBlock import org.domaframework.doma.intellij.formatter.block.conflict.SqlConflictExpressionSubGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.condition.SqlConditionKeywordGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.condition.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.option.SqlInGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlReturningGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlValuesGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlWhereGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlFunctionParamBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlParallelListBlock import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlValuesParamGroupBlock @@ -96,14 +95,7 @@ object NotQueryGroupHandler { private fun hasFunctionOrAliasContext(lastGroup: SqlBlock?): Boolean { val lastChild = lastGroup?.childBlocks?.lastOrNull() if (lastChild != null) { - when (lastChild) { - is SqlElConditionLoopCommentBlock -> { - if (lastChild.isBeforeParentBlock()) { - return lastChild.parentBlock is SqlWordBlock - } - } - else -> return lastGroup.childBlocks.lastOrNull() is SqlWordBlock - } + return lastGroup.childBlocks.lastOrNull() is SqlWordBlock } return false } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlBlockGenerator.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlBlockGenerator.kt index b2f24885..5997cab2 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlBlockGenerator.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlBlockGenerator.kt @@ -108,6 +108,7 @@ class SqlBlockGenerator( fun getKeywordBlock( child: ASTNode, lastGroupBlock: SqlBlock?, + openConditionLoopDirective: SqlElConditionLoopCommentBlock?, ): SqlBlock { val keywordText = child.text.lowercase() @@ -120,7 +121,7 @@ class SqlBlockGenerator( return when (indentLevel) { IndentType.INLINE -> keywordBlockFactory.createInlineBlock(child, lastGroupBlock) IndentType.ATTACHED -> keywordBlockFactory.createAttachedBlock(child, lastGroupBlock) - IndentType.OPTIONS -> keywordBlockFactory.createOptionsBlock(keywordText, child, lastGroupBlock) + IndentType.OPTIONS -> keywordBlockFactory.createOptionsBlock(keywordText, child, lastGroupBlock, openConditionLoopDirective) IndentType.CONFLICT -> keywordBlockFactory.createConflictBlock(keywordText, child, lastGroupBlock) else -> SqlKeywordBlock(child, indentLevel, sqlBlockFormattingCtx) } @@ -418,6 +419,10 @@ class SqlBlockGenerator( return null } + /** + * If the previous group is a keyword group, it becomes a table name block under specific conditions + * After [SqlColumnRawGroupBlock] etc., it becomes a normal [SqlWordBlock] + */ fun getWordBlock( lastGroup: SqlBlock?, child: ASTNode, @@ -530,12 +535,7 @@ class SqlBlockGenerator( } } - private fun getRootBlock(lastGroupBlock: SqlBlock?): SqlBlock? = - if (lastGroupBlock is SqlElConditionLoopCommentBlock) { - lastGroupBlock.tempParentBlock - } else { - lastGroupBlock - } + private fun getRootBlock(lastGroupBlock: SqlBlock?): SqlBlock? = lastGroupBlock private fun createConditionBlock( child: ASTNode, diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlKeywordBlockFactory.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlKeywordBlockFactory.kt index afa1772a..4070ac22 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlKeywordBlockFactory.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlKeywordBlockFactory.kt @@ -70,6 +70,7 @@ class SqlKeywordBlockFactory( keywordText: String, child: ASTNode, lastGroupBlock: SqlBlock?, + openConditionLoopDirective: SqlElConditionLoopCommentBlock?, ): SqlBlock { // Handle AS keyword for CREATE VIEW if (keywordText == "as") { @@ -91,7 +92,7 @@ class SqlKeywordBlockFactory( // Handle EXISTS/NOT EXISTS keywords if (SqlKeywordUtil.isExistsKeyword(keywordText)) { - return createExistsBlock(keywordText, child, lastGroupBlock) + return createExistsBlock(keywordText, child, lastGroupBlock, openConditionLoopDirective) } return SqlKeywordBlock(child, IndentType.OPTIONS, sqlBlockFormattingCtx) @@ -119,16 +120,20 @@ class SqlKeywordBlockFactory( keywordText: String, child: ASTNode, lastGroupBlock: SqlBlock?, + openConditionLoopDirective: SqlElConditionLoopCommentBlock?, ): SqlBlock { + val afterConditionLoopCommentBlock = openConditionLoopDirective != null && openConditionLoopDirective.getDependsOnBlock() == null // If already in EXISTS group, just return a keyword block - if (lastGroupBlock is SqlExistsGroupBlock) { + if (lastGroupBlock is SqlExistsGroupBlock && !afterConditionLoopCommentBlock) { return SqlKeywordBlock(child, IndentType.OPTIONS, sqlBlockFormattingCtx) } // Check for ELSE condition or NOT keyword outside WHERE/condition context val shouldCreateExistsGroup = when { - lastGroupBlock is SqlElConditionLoopCommentBlock && lastGroupBlock.conditionType.isElse() -> true + openConditionLoopDirective?.conditionLoopDirective == null && + openConditionLoopDirective?.conditionType?.isElse() == true -> true + afterConditionLoopCommentBlock -> true lastGroupBlock is SqlCreateTableColumnDefinitionGroupBlock || lastGroupBlock is SqlCreateTableColumnDefinitionRawGroupBlock -> false keywordText == "not" && !isInConditionContext(lastGroupBlock) -> true diff --git a/src/test/kotlin/org/domaframework/doma/intellij/formatter/SqlFormatterTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/formatter/SqlFormatterTest.kt index a9ca5bae..98147835 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/formatter/SqlFormatterTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/formatter/SqlFormatterTest.kt @@ -110,6 +110,10 @@ class SqlFormatterTest : BasePlatformTestCase() { formatSqlFile("Update.sql", "Update$formatDataPrefix.sql") } + fun testUpdatePopulateFormatter() { + formatSqlFile("UpdatePopulate.sql", "UpdatePopulate$formatDataPrefix.sql") + } + fun testUpdateReturningFormatter() { formatSqlFile("UpdateReturning.sql", "UpdateReturning$formatDataPrefix.sql") } diff --git a/src/test/testData/sql/formatter/AlterTableAddColumn_format.sql b/src/test/testData/sql/formatter/AlterTableAddColumn_format.sql index 35ad5dcd..f63cedb9 100644 --- a/src/test/testData/sql/formatter/AlterTableAddColumn_format.sql +++ b/src/test/testData/sql/formatter/AlterTableAddColumn_format.sql @@ -5,4 +5,4 @@ ALTER TABLE /*# tableName */ , /*%end */ /*%end */ - DROP COLUMN /*# column2.name */ /*# column2.type */ + DROP COLUMN /*# column2.name */ /*# column2.type */ diff --git a/src/test/testData/sql/formatter/ComparisonOperators_format.sql b/src/test/testData/sql/formatter/ComparisonOperators_format.sql index d0efabe4..0da104cc 100644 --- a/src/test/testData/sql/formatter/ComparisonOperators_format.sql +++ b/src/test/testData/sql/formatter/ComparisonOperators_format.sql @@ -21,7 +21,7 @@ SELECT id tags && ARRAY[/*%for property : properties */ /* property */'property' /*%if property_has_next*/ - , + , /*%end*/ /*%end*/] AS is_urgent , ARRAY['tag1', 'tag2'] <@ tags AS has_all_tags diff --git a/src/test/testData/sql/formatter/ConditionalSubquery.sql b/src/test/testData/sql/formatter/ConditionalSubquery.sql index d6a203d2..25c084d0 100644 --- a/src/test/testData/sql/formatter/ConditionalSubquery.sql +++ b/src/test/testData/sql/formatter/ConditionalSubquery.sql @@ -1,21 +1,15 @@ SELECT e.id , e.name -, -/*%if includeSkillCount */ -( SELECT COUNT(DISTINCT es.skill_id) -FROM employee_skills es -/*%if onlyActiveSkills */ -INNER JOIN skills sk ON es.skill_id = sk.id -WHERE es.employee_id = e.id -AND sk.is_active = true -/*%if skillCategories != null && skillCategories.size() > 0 */ -AND sk.category IN /* skillCategories */('technical', 'management') -/*%end*/ -/*%else*/ -WHERE es.employee_id = e.id -/*%end*/ ), -/*%end*/ -d.department_name +, /*%if includeSkillCount */ + ( SELECT COUNT(DISTINCT es.skill_id) + FROM performance_reviews pr WHERE pr.employee_id = e.id +/*%if reviewPeriod != null */ +AND pr.review_date BETWEEN /* reviewPeriod.startDate */'2023-01-01' AND /* reviewPeriod.endDate */'2023-12-31' /*%end*/ +/*%if minScore != null */ +AND pr.performance_score >= /* minScore */4.0 +/*%end*/ ) , + /*%end*/ + d.department_name FROM employees e INNER JOIN departments d ON e.department_id = d.id WHERE/*%if filterByHighPerformers */ diff --git a/src/test/testData/sql/formatter/ConditionalSubquery_format.sql b/src/test/testData/sql/formatter/ConditionalSubquery_format.sql index d6f9e444..c9ec5ee9 100644 --- a/src/test/testData/sql/formatter/ConditionalSubquery_format.sql +++ b/src/test/testData/sql/formatter/ConditionalSubquery_format.sql @@ -2,19 +2,15 @@ SELECT e.id , e.name , /*%if includeSkillCount */ ( SELECT COUNT(DISTINCT es.skill_id) - FROM employee_skills es - /*%if onlyActiveSkills */ - INNER JOIN skills sk - ON es.skill_id = sk.id - WHERE es.employee_id = e.id - AND sk.is_active = true - /*%if skillCategories != null && skillCategories.size() > 0 */ - AND sk.category IN /* skillCategories */('technical', 'management') - /*%end*/ - /*%else*/ - WHERE es.employee_id = e.id - /*%end*/ ) - , + FROM performance_reviews pr + WHERE pr.employee_id = e.id + /*%if reviewPeriod != null */ + AND pr.review_date BETWEEN /* reviewPeriod.startDate */'2023-01-01' AND /* reviewPeriod.endDate */'2023-12-31' + /*%end*/ + /*%if minScore != null */ + AND pr.performance_score >= /* minScore */4.0 + /*%end*/ ) + , /*%end*/ d.department_name FROM employees e diff --git a/src/test/testData/sql/formatter/LoopDirective_format.sql b/src/test/testData/sql/formatter/LoopDirective_format.sql index 01b1a35e..c48f9d25 100644 --- a/src/test/testData/sql/formatter/LoopDirective_format.sql +++ b/src/test/testData/sql/formatter/LoopDirective_format.sql @@ -3,7 +3,7 @@ SELECT /*%if column_index == 0 */ /* column.name */'id' AS /* column.alias */'user_id' /*%else*/ - , /* column.name */'name' AS /* column.alias */'user_name' + , /* column.name */'name' AS /* column.alias */'user_name' /*%end*/ /*%end*/ FROM users diff --git a/src/test/testData/sql/formatter/NestedDirectives_format.sql b/src/test/testData/sql/formatter/NestedDirectives_format.sql index 9d6ee1f6..b9d66c67 100644 --- a/src/test/testData/sql/formatter/NestedDirectives_format.sql +++ b/src/test/testData/sql/formatter/NestedDirectives_format.sql @@ -43,7 +43,7 @@ SELECT e.id /*%end */ -- END3 /*%if sort_has_next */ -- IF8 e.sort_field - , + , /*%end */ -- END8 /*%end */ -- END2 /*%else */ -- ELSE1 diff --git a/src/test/testData/sql/formatter/OrderByGroupWithConditionDirective.sql b/src/test/testData/sql/formatter/OrderByGroupWithConditionDirective.sql index 69945a1f..7b874c94 100644 --- a/src/test/testData/sql/formatter/OrderByGroupWithConditionDirective.sql +++ b/src/test/testData/sql/formatter/OrderByGroupWithConditionDirective.sql @@ -1,13 +1,10 @@ SELECT e.id -- with condition , ROW_NUMBER() /*%if order */OVER(ORDER BY e.manager_id DESC)/*%end*/ AS row_num - , RANK() OVER(PARTITION BY department_id -/*%if order */ORDER BY e.manager_id DESC/*%end */ -ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS rank_num , DENSE_RANK() OVER(PARTITION BY department_id - /*%if order */ + ORDER BY e.id ASC, e.manager_id ASC, created_at DESC - /*%else */ + /*%if rows */ ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING/*%end */) AS dense_rank_num , SUM(amount)/*%if filter */ FILTER(WHERE status = 'active')/*%end*/ AS dept_salary_avg , COUNT(*) OVER(ORDER BY e.id, e.manager_id, created_at diff --git a/src/test/testData/sql/formatter/OrderByGroupWithConditionDirective_format.sql b/src/test/testData/sql/formatter/OrderByGroupWithConditionDirective_format.sql index 1f4fe159..8c57cf04 100644 --- a/src/test/testData/sql/formatter/OrderByGroupWithConditionDirective_format.sql +++ b/src/test/testData/sql/formatter/OrderByGroupWithConditionDirective_format.sql @@ -5,15 +5,9 @@ SELECT e.id OVER(ORDER BY e.manager_id DESC) /*%end*/ AS row_num - , RANK() OVER(PARTITION BY department_id - /*%if order */ - ORDER BY e.manager_id DESC - /*%end */ - ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS rank_num , DENSE_RANK() OVER(PARTITION BY department_id - /*%if order */ ORDER BY e.id ASC, e.manager_id ASC, created_at DESC - /*%else */ + /*%if rows */ ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING /*%end */) AS dense_rank_num , SUM(amount) diff --git a/src/test/testData/sql/formatter/SelectDirectiveTestData.sql b/src/test/testData/sql/formatter/SelectDirectiveTestData.sql index 07cd7e3b..4fd5d3cb 100644 --- a/src/test/testData/sql/formatter/SelectDirectiveTestData.sql +++ b/src/test/testData/sql/formatter/SelectDirectiveTestData.sql @@ -1,6 +1,4 @@ SELECT /*%expand */ * -, /*%populate */ -, extra FROM ( SELECT * FROM users ) AS u , ( SELECT tag FROM post WHERE u.usr_id = /*authr.id*/0 ) AS tag , employee where common_id = /*@ example.status. CommonStatus @ id*/1 diff --git a/src/test/testData/sql/formatter/SelectDirectiveTestData_format.sql b/src/test/testData/sql/formatter/SelectDirectiveTestData_format.sql index 7afec86e..1161c25b 100644 --- a/src/test/testData/sql/formatter/SelectDirectiveTestData_format.sql +++ b/src/test/testData/sql/formatter/SelectDirectiveTestData_format.sql @@ -1,6 +1,4 @@ SELECT /*%expand */* - , /*%populate */ - , extra FROM ( SELECT * FROM users ) AS u , ( SELECT tag diff --git a/src/test/testData/sql/formatter/UpdatePopulate.sql b/src/test/testData/sql/formatter/UpdatePopulate.sql new file mode 100644 index 00000000..73f452a5 --- /dev/null +++ b/src/test/testData/sql/formatter/UpdatePopulate.sql @@ -0,0 +1,2 @@ +UPDATE employee SET /*%populate*/ id = id + WHERE age < 30 \ No newline at end of file diff --git a/src/test/testData/sql/formatter/UpdatePopulate_format.sql b/src/test/testData/sql/formatter/UpdatePopulate_format.sql new file mode 100644 index 00000000..4403d557 --- /dev/null +++ b/src/test/testData/sql/formatter/UpdatePopulate_format.sql @@ -0,0 +1,3 @@ +UPDATE employee + SET /*%populate*/ id = id + WHERE age < 30 diff --git a/src/test/testData/sql/formatter/UseDirectiveWithQuery.sql b/src/test/testData/sql/formatter/UseDirectiveWithQuery.sql index 7adfd6db..310da819 100644 --- a/src/test/testData/sql/formatter/UseDirectiveWithQuery.sql +++ b/src/test/testData/sql/formatter/UseDirectiveWithQuery.sql @@ -1,30 +1,32 @@ /*%if useWith */ -WITH -/*%for cte : cteDefinitions */ -/* cte.name */user_stats AS ( -/*# cte.query */SELECT user_id, COUNT(*) as order_count FROM orders GROUP BY user_id -) - /*%if cte_has_next */,/*%end*/ -/*%end*/ +WITH + /*%for cte : cteDefinitions */ + user_stats AS (/*# cte.query */ + SELECT user_id + , COUNT(*) AS order_count + FROM orders + GROUP BY user_id) + /*%if cte_has_next */ + , + /*%end*/ + /*%end*/ /*%end*/ +SELECT u.id + , u.name + /*%if useWith */ + , us.order_count + /*%end*/ + FROM users u + /*%if useWith */ + /*%for cte : cteDefinitions */ + LEFT JOIN user_stats us + ON u.id = us.user_id + /*%end*/ + /*%end*/ +UNION ALL SELECT -u.id, -u.name - /*%if useWith */ - , us.order_count - /*%end*/ -FROM users u -/*%if useWith */ - /*%for cte : cteDefinitions */ - LEFT JOIN /* cte.name */user_stats us ON u.id = us.user_id - /*%end*/ -/*%end*/ - -/*%for query : unionQueries */ - /*%if query_index > 0 */ - UNION ALL - /*%end*/ - SELECT /* query.columns */id, name - FROM /* query.tableName */users - WHERE /* query.condition */active = true -/*%end*/ \ No newline at end of file + /*%for query : unionQueries */ + /*# query.columns */ + /*%end*/ + FROM /*# tableName */ + WHERE active = /* condition */true diff --git a/src/test/testData/sql/formatter/UseDirectiveWithQuery_format.sql b/src/test/testData/sql/formatter/UseDirectiveWithQuery_format.sql index 0c480d94..5b704e68 100644 --- a/src/test/testData/sql/formatter/UseDirectiveWithQuery_format.sql +++ b/src/test/testData/sql/formatter/UseDirectiveWithQuery_format.sql @@ -1,15 +1,15 @@ /*%if useWith */ WITH /*%for cte : cteDefinitions */ - /* cte.name */ user_stats AS ( + user_stats AS ( /*# cte.query */ SELECT user_id , COUNT(*) AS order_count FROM orders GROUP BY user_id -) + ) /*%if cte_has_next */ - , + , /*%end*/ /*%end*/ /*%end*/ @@ -21,16 +21,14 @@ SELECT u.id FROM users u /*%if useWith */ /*%for cte : cteDefinitions */ - LEFT JOIN /* cte.name */user_stats us + LEFT JOIN user_stats us ON u.id = us.user_id /*%end*/ /*%end*/ -/*%for query : unionQueries */ - /*%if query_index > 0 */ - UNION ALL - /*%end*/ -SELECT /* query.columns */id - , name - FROM /* query.tableName */users - WHERE /* query.condition */active = true -/*%end*/ +UNION ALL +SELECT + /*%for query : unionQueries */ + /*# query.columns */ + /*%end*/ + FROM /*# tableName */ + WHERE active = /* condition */true diff --git a/src/test/testData/sql/formatter/UserDirectiveSelectQuery_format.sql b/src/test/testData/sql/formatter/UserDirectiveSelectQuery_format.sql index 32d00d61..9483b5bf 100644 --- a/src/test/testData/sql/formatter/UserDirectiveSelectQuery_format.sql +++ b/src/test/testData/sql/formatter/UserDirectiveSelectQuery_format.sql @@ -3,7 +3,7 @@ SELECT p.id , p.price , /*%if includeTax */ p.price * /* taxRate */1.1 AS price_with_tax - , + , /*%end*/ p.stock_quantity FROM products p