Formatter: fix line break between declarations with comment

#KT-12490 Fixed
#KT-35088 Fixed
This commit is contained in:
Dmitry Gridin
2019-11-15 21:57:37 +07:00
parent b6b755506c
commit bfd539d5d1
49 changed files with 191 additions and 12 deletions
@@ -17,7 +17,8 @@ import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.idea.util.requireNode
import org.jetbrains.kotlin.lexer.KtTokens
import java.util.*
import org.jetbrains.kotlin.psi.psiUtil.children
import org.jetbrains.kotlin.psi.stubs.elements.KtModifierListElementType
import kotlin.math.max
fun CommonCodeStyleSettings.createSpaceBeforeRBrace(numSpacesOtherwise: Int, textRange: TextRange): Spacing? {
@@ -103,13 +104,20 @@ class KotlinSpacingBuilder(val commonCodeStyleSettings: CommonCodeStyleSettings,
val lastChild = left.node?.psi?.lastChild
val leftEndsWithComment = lastChild is PsiComment && lastChild.tokenType == KtTokens.EOL_COMMENT
val dependentSpacingRule = DependentSpacingRule(Trigger.HAS_LINE_FEEDS).registerData(Anchor.MIN_LINE_FEEDS, emptyLines + 1)
val textRange = left.node
?.children()
?.firstOrNull { it.elementType !in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET }
?.startOffset
?.let { TextRange.create(it, left.textRange.endOffset) }
?: left.textRange
spacingBuilderUtil.createLineFeedDependentSpacing(
numSpacesOtherwise,
numSpacesOtherwise,
if (leftEndsWithComment) max(1, numberOfLineFeedsOtherwise) else numberOfLineFeedsOtherwise,
commonCodeStyleSettings.KEEP_LINE_BREAKS,
commonCodeStyleSettings.KEEP_BLANK_LINES_IN_DECLARATIONS,
left.textRange,
textRange,
dependentSpacingRule
)
}
@@ -200,3 +208,8 @@ fun rules(
builder.init()
return builder
}
internal fun ASTNode.startOfDeclaration(): ASTNode? = children().firstOrNull {
val elementType = it.elementType
elementType !is KtModifierListElementType<*> && elementType !in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET
}
@@ -12,6 +12,7 @@ import com.intellij.formatting.SpacingBuilder
import com.intellij.formatting.SpacingBuilder.RuleBuilder
import com.intellij.lang.ASTNode
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.codeStyle.CodeStyleSettings
@@ -32,6 +33,8 @@ val MODIFIERS_LIST_ENTRIES = TokenSet.orSet(TokenSet.create(ANNOTATION_ENTRY, AN
val EXTEND_COLON_ELEMENTS =
TokenSet.create(TYPE_CONSTRAINT, CLASS, OBJECT_DECLARATION, TYPE_PARAMETER, ENUM_ENTRY, SECONDARY_CONSTRUCTOR)
val DECLARATIONS = TokenSet.create(PROPERTY, FUN, CLASS, OBJECT_DECLARATION, ENUM_ENTRY, SECONDARY_CONSTRUCTOR, CLASS_INITIALIZER)
fun SpacingBuilder.beforeInside(element: IElementType, tokenSet: TokenSet, spacingFun: RuleBuilder.() -> Unit) {
tokenSet.types.forEach { inType -> beforeInside(element, inType).spacingFun() }
}
@@ -47,9 +50,6 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing
val kotlinCommonSettings = settings.kotlinCommonSettings
val kotlinCustomSettings = settings.kotlinCustomSettings
return rules(kotlinCommonSettings, builderUtil) {
val DECLARATIONS =
TokenSet.create(PROPERTY, FUN, CLASS, OBJECT_DECLARATION, ENUM_ENTRY, SECONDARY_CONSTRUCTOR, CLASS_INITIALIZER)
simple {
before(FILE_ANNOTATION_LIST).lineBreakInCode()
after(FILE_ANNOTATION_LIST).blankLines(1)
@@ -87,8 +87,21 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing
null
}
}
inPosition(right = BLOCK_COMMENT).spacing(commentSpacing(0))
inPosition(right = EOL_COMMENT).spacing(commentSpacing(1))
inPosition(leftSet = DECLARATIONS, rightSet = DECLARATIONS).customRule(fun(
_: ASTBlock,
_: ASTBlock,
right: ASTBlock
): Spacing? {
val firstChild = right.node?.firstChildNode as? PsiComment ?: return null
val whiteSpace = firstChild.nextSibling as? PsiWhiteSpace ?: return null
return if (StringUtil.containsLineBreak(firstChild.text) || StringUtil.containsLineBreak(whiteSpace.text)) {
createSpacing(0, minLineFeeds = 2)
} else
null
})
inPosition(left = CLASS, right = CLASS).emptyLinesIfLineBreakInLeft(1)
inPosition(left = CLASS, right = OBJECT_DECLARATION).emptyLinesIfLineBreakInLeft(1)