Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ import com.intellij.formatting.SpacingBuilder
import com.intellij.formatting.Wrap
import com.intellij.lang.ASTNode
import com.intellij.psi.formatter.common.AbstractBlock
import org.domaframework.doma.intellij.formatter.block.comment.SqlBlockCommentBlock
import org.domaframework.doma.intellij.formatter.block.comment.SqlLineCommentBlock
import org.domaframework.doma.intellij.formatter.block.comment.SqlCommentBlock
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.SqlNewGroupBlock
import org.domaframework.doma.intellij.formatter.builder.SqlCustomSpacingBuilder
import org.domaframework.doma.intellij.formatter.util.IndentType
import org.domaframework.doma.intellij.formatter.util.SqlKeywordUtil
import org.domaframework.doma.intellij.psi.SqlTypes
import org.jetbrains.kotlin.psi.psiUtil.startOffset

open class SqlBlock(
node: ASTNode,
Expand Down Expand Up @@ -59,32 +63,31 @@ open class SqlBlock(

open var parentBlock: SqlBlock? = null
open val childBlocks = mutableListOf<SqlBlock>()
open var prevBlocks = emptyList<SqlBlock>()

fun getChildrenTextLen(): Int =
childBlocks.sumOf { child ->
val children =
child.childBlocks.filter { it !is SqlLineCommentBlock && it !is SqlBlockCommentBlock }
if (children.isNotEmpty()) {
child
.getChildrenTextLen()
.plus(child.getNodeText().length)
} else if (child.node.elementType == SqlTypes.DOT ||
child.node.elementType == SqlTypes.RIGHT_PAREN
) {
// Since elements do not include surrounding spaces, they should be excluded from the character count.
0
} else {
child.getNodeText().length.plus(1)
}
fun getChildrenTextLen(): Int = childBlocks.sumOf { child -> calculateChildTextLength(child) }

private fun calculateChildTextLength(child: SqlBlock): Int {
val nonCommentChildren = child.childBlocks.filterNot { it is SqlDefaultCommentBlock }

if (nonCommentChildren.isNotEmpty()) {
return child.getChildrenTextLen() + child.getNodeText().length
}
if (isExcludedFromTextLength(child)) {
return 0
}
return child.getNodeText().length + 1
}

private fun isExcludedFromTextLength(block: SqlBlock): Boolean = block.node.elementType in setOf(SqlTypes.DOT, SqlTypes.RIGHT_PAREN)

fun getChildBlocksDropLast(
dropIndex: Int = 1,
skipCommentBlock: Boolean = false,
skipCommentBlock: Boolean = true,
): List<SqlBlock> {
val children = childBlocks.dropLast(dropIndex)
if (skipCommentBlock) {
return children.filter { it !is SqlLineCommentBlock && it !is SqlBlockCommentBlock }
return children.filter { it !is SqlDefaultCommentBlock }
}
return children
}
Expand All @@ -98,6 +101,7 @@ open class SqlBlock(

open fun setParentGroupBlock(lastGroup: SqlBlock?) {
parentBlock = lastGroup
prevBlocks = parentBlock?.childBlocks?.toList() ?: emptyList()
parentBlock?.addChildBlock(this)
setParentPropertyBlock(lastGroup)
}
Expand All @@ -107,14 +111,58 @@ open class SqlBlock(
}

open fun addChildBlock(childBlock: SqlBlock) {
childBlocks.add(childBlock)
if (!childBlocks.contains(childBlock)) {
childBlocks.add(childBlock)
}
}

fun getNodeText() = node.text.lowercase()

fun isEnableFormat(): Boolean = enableFormat

open fun isSaveSpace(lastGroup: SqlBlock?): Boolean = false
open fun isSaveSpace(lastGroup: SqlBlock?): Boolean =
parentBlock?.let { parent ->
when (parent) {
is SqlElConditionLoopCommentBlock -> shouldSaveSpaceForConditionLoop(parent)
is SqlNewGroupBlock -> shouldSaveSpaceForNewGroup(parent)
else -> false
}
} == true

private fun shouldSaveSpaceForConditionLoop(parent: SqlElConditionLoopCommentBlock): Boolean {
val prevBlock = prevBlocks.lastOrNull { it !is SqlDefaultCommentBlock }
val isPrevBlockElseOrEnd =
prevBlock is SqlElConditionLoopCommentBlock &&
(prevBlock.conditionType.isElse() || prevBlock.conditionType.isEnd())
val hasNoChildrenExceptLast = parent.childBlocks.dropLast(1).isEmpty()

return isPrevBlockElseOrEnd || hasNoChildrenExceptLast
}

private fun shouldSaveSpaceForNewGroup(parent: SqlNewGroupBlock): Boolean {
val prevWord = prevBlocks.lastOrNull { it !is SqlCommentBlock }

if (isNonBreakingKeywordCombination(parent, prevWord)) {
return false
}

return isFollowedByConditionLoop() || isPrecededByConditionLoop(parent)
}

private fun isNonBreakingKeywordCombination(
parent: SqlNewGroupBlock,
prevWord: SqlBlock?,
): Boolean =
SqlKeywordUtil.isSetLineKeyword(getNodeText(), parent.getNodeText()) ||
SqlKeywordUtil.isSetLineKeyword(getNodeText(), prevWord?.getNodeText() ?: "")

private fun isFollowedByConditionLoop(): Boolean = childBlocks.lastOrNull() is SqlElConditionLoopCommentBlock

private fun isPrecededByConditionLoop(parent: SqlNewGroupBlock): Boolean {
val lastPrevBlock = prevBlocks.lastOrNull()
return lastPrevBlock is SqlElConditionLoopCommentBlock &&
lastPrevBlock.node.psi.startOffset > parent.node.psi.startOffset
}

/**
* Creates the indentation length for the block.
Expand Down Expand Up @@ -157,11 +205,15 @@ open class SqlBlock(
*/
override fun getChildIndent(): Indent? =
if (isEnableFormat()) {
Indent.getSpaceIndent(4)
Indent.getSpaceIndent(DEFAULT_INDENT_SIZE)
} else {
Indent.getSpaceIndent(0)
}

companion object {
private const val DEFAULT_INDENT_SIZE = 4
}

/**
* Determines whether the block is a leaf node.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package org.domaframework.doma.intellij.formatter.block
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.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
Expand Down Expand Up @@ -58,6 +59,7 @@ open class SqlCommaBlock(
SqlFunctionParamBlock::class,
SqlWithColumnGroupBlock::class,
SqlKeywordGroupBlock::class,
SqlElConditionLoopCommentBlock::class,
)

private val PARENT_INDENT_SYNC_TYPES =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ import com.intellij.formatting.Wrap
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.formatter.common.AbstractBlock
import org.domaframework.doma.intellij.formatter.block.comment.SqlBlockCommentBlock
import org.domaframework.doma.intellij.common.util.TypeUtil
import org.domaframework.doma.intellij.formatter.block.comment.SqlCommentBlock
import org.domaframework.doma.intellij.formatter.block.comment.SqlDefaultCommentBlock
import org.domaframework.doma.intellij.formatter.block.comment.SqlElBlockCommentBlock
import org.domaframework.doma.intellij.formatter.block.comment.SqlElConditionLoopCommentBlock
import org.domaframework.doma.intellij.formatter.block.comment.SqlLineCommentBlock
import org.domaframework.doma.intellij.formatter.block.expr.SqlElBlockCommentBlock
import org.domaframework.doma.intellij.formatter.block.expr.SqlElConditionLoopCommentBlock
import org.domaframework.doma.intellij.formatter.block.expr.SqlElSymbolBlock
import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock
import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnBlock
Expand All @@ -50,15 +51,17 @@ import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubGrou
import org.domaframework.doma.intellij.formatter.block.group.subgroup.SqlSubQueryGroupBlock
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.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
import org.domaframework.doma.intellij.formatter.builder.SqlCustomSpacingBuilder
import org.domaframework.doma.intellij.formatter.handler.CreateClauseHandler
import org.domaframework.doma.intellij.formatter.processor.SqlSetParentGroupProcessor
import org.domaframework.doma.intellij.formatter.util.CreateTableUtil
import org.domaframework.doma.intellij.formatter.util.IndentType
import org.domaframework.doma.intellij.formatter.util.SqlBlockFormattingContext
import org.domaframework.doma.intellij.formatter.util.SqlBlockUtil
import org.domaframework.doma.intellij.formatter.util.SqlBlockGenerator
import org.domaframework.doma.intellij.psi.SqlTypes

class SqlFileBlock(
Expand All @@ -77,11 +80,22 @@ class SqlFileBlock(
enableFormat,
formatMode,
) {
override val indent =
ElementIndent(
IndentType.FILE,
0,
0,
)

override fun setParentGroupBlock(lastGroup: SqlBlock?) {
super.setParentGroupBlock(null)
}

private val blocks = mutableListOf<AbstractBlock>()

private val blockBuilder = SqlBlockBuilder()
private val parentSetProcessor = SqlSetParentGroupProcessor(blockBuilder)
private val blockUtil = SqlBlockUtil(this, isEnableFormat(), formatMode)
private val blockUtil = SqlBlockGenerator(this, isEnableFormat(), formatMode)

private val pendingCommentBlocks = mutableListOf<SqlBlock>()

Expand Down Expand Up @@ -251,7 +265,11 @@ class SqlFileBlock(
commentBlock,
)
} else {
blockBuilder.addCommentBlock(commentBlock)
(commentBlock as? SqlDefaultCommentBlock)?.let {
blockBuilder.addCommentBlock(
commentBlock,
)
}
}
}

Expand Down Expand Up @@ -295,6 +313,8 @@ class SqlFileBlock(
return
}

if (childBlock is SqlDefaultCommentBlock) return

when (childBlock) {
is SqlKeywordGroupBlock -> {
parentSetProcessor.updateKeywordGroupBlockParentAndAddGroup(
Expand Down Expand Up @@ -345,7 +365,7 @@ class SqlFileBlock(
)
}

is SqlWordBlock, is SqlOtherBlock, is SqlLineCommentBlock, is SqlBlockCommentBlock -> {
is SqlWordBlock, is SqlOtherBlock -> {
parentSetProcessor.updateGroupBlockParentAndAddGroup(
childBlock,
)
Expand Down Expand Up @@ -440,6 +460,25 @@ class SqlFileBlock(
return SqlCustomSpacingBuilder().getSpacing(childBlock2)
}

if (childBlock1 is SqlWhitespaceBlock && childBlock2.parentBlock is SqlElConditionLoopCommentBlock) {
val child1 = childBlock2.parentBlock as SqlElConditionLoopCommentBlock
SqlCustomSpacingBuilder()
.getSpacingElDirectiveComment(child1, childBlock2)
?.let { return it }
}

if (childBlock1 is SqlElBlockCommentBlock && childBlock2 !is SqlRightPatternBlock) {
SqlCustomSpacingBuilder()
.getSpacingElDirectiveComment(childBlock1, childBlock2)
?.let { return it }
}

if (childBlock2 is SqlRightPatternBlock) {
return SqlCustomSpacingBuilder().getSpacingRightPattern(
childBlock2,
)
}

if (childBlock2 is SqlWithColumnGroupBlock) {
return SqlCustomSpacingBuilder.normalSpacing
}
Expand All @@ -454,8 +493,15 @@ class SqlFileBlock(
}

if (childBlock2 is SqlElBlockCommentBlock) {
if (TypeUtil.isExpectedClassType(
SqlRightPatternBlock.NOT_INDENT_EXPECTED_TYPES,
childBlock1,
)
) {
return SqlCustomSpacingBuilder.nonSpacing
}
return when (childBlock1) {
is SqlElBlockCommentBlock, is SqlWhitespaceBlock -> {
is SqlWhitespaceBlock -> {
SqlCustomSpacingBuilder().getSpacing(childBlock2)
}

Expand Down Expand Up @@ -488,14 +534,6 @@ class SqlFileBlock(
return SqlCustomSpacingBuilder().getSpacing(childBlock2)
}

if (childBlock1 is SqlWhitespaceBlock) {
when (childBlock2) {
is SqlBlockCommentBlock, is SqlLineCommentBlock, is SqlNewGroupBlock -> {
return SqlCustomSpacingBuilder().getSpacing(childBlock2)
}
}
}

if (childBlock2 is SqlNewGroupBlock) {
if (childBlock1 is SqlSubGroupBlock && childBlock2.indent.indentLevel == IndentType.ATTACHED) {
return SqlCustomSpacingBuilder.nonSpacing
Expand All @@ -509,12 +547,14 @@ class SqlFileBlock(

is SqlDataTypeParamBlock, is SqlFunctionParamBlock -> return SqlCustomSpacingBuilder.nonSpacing

else -> return SqlCustomSpacingBuilder.normalSpacing
// else -> return SqlCustomSpacingBuilder.normalSpacing
}
}

// Create Table Column Definition Raw Group Block
CreateTableUtil.getColumnDefinitionRawGroupSpacing(childBlock1, childBlock2)?.let { return it }
CreateClauseHandler
.getColumnDefinitionRawGroupSpacing(childBlock1, childBlock2)
?.let { return it }

when (childBlock2) {
is SqlColumnDefinitionRawGroupBlock ->
Expand All @@ -523,18 +563,32 @@ class SqlFileBlock(
childBlock2,
)?.let { return it }

is SqlRightPatternBlock -> return SqlCustomSpacingBuilder().getSpacingRightPattern(
childBlock2,
)

is SqlColumnBlock ->
SqlCustomSpacingBuilder()
.getSpacingColumnDefinition(childBlock2)
?.let { return it }
}

if (childBlock1 is SqlBlock && (childBlock2 is SqlCommaBlock || childBlock2 is SqlColumnRawGroupBlock)) {
SqlCustomSpacingBuilder().getSpacingWithIndentComma(childBlock1, childBlock2)?.let { return it }
SqlCustomSpacingBuilder()
.getSpacingWithIndentComma(childBlock1, childBlock2)
?.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
}

val spacing: Spacing? = customSpacingBuilder?.getCustomSpacing(childBlock1, childBlock2)
Expand Down
Loading
Loading