Apply indent of continuation call start to its children
#KT-15099 Fixed
This commit is contained in:
@@ -20,6 +20,7 @@ import com.intellij.injected.editor.VirtualFileWindow
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.source.tree.TreeUtil
|
||||
import com.intellij.psi.search.PsiSearchScopeUtil
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
@@ -400,3 +401,11 @@ fun ASTNode.siblings(forward: Boolean = true): Sequence<ASTNode> {
|
||||
return generateSequence(treePrev) { it.treePrev }
|
||||
}
|
||||
}
|
||||
|
||||
fun ASTNode.leaves(forward: Boolean = true): Sequence<ASTNode> {
|
||||
if (forward) {
|
||||
return generateSequence(TreeUtil.nextLeaf(this)) { TreeUtil.nextLeaf(it) }
|
||||
} else {
|
||||
return generateSequence(TreeUtil.prevLeaf(this)) { TreeUtil.prevLeaf(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,10 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.children
|
||||
import org.jetbrains.kotlin.psi.psiUtil.leaves
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
|
||||
private val QUALIFIED_OPERATION = TokenSet.create(DOT, SAFE_ACCESS)
|
||||
private val QUALIFIED_EXPRESSIONS = TokenSet.create(KtNodeTypes.DOT_QUALIFIED_EXPRESSION, KtNodeTypes.SAFE_ACCESS_EXPRESSION)
|
||||
@@ -118,11 +120,13 @@ abstract class KotlinCommonBlock(
|
||||
// Create fake ".something" or "?.something" block here, so child indentation will be
|
||||
// relative to it when it starts from new line (see Indent javadoc).
|
||||
|
||||
val indent = if (settings.kotlinCustomSettings.CONTINUATION_INDENT_FOR_CHAINED_CALLS)
|
||||
Indent.getContinuationWithoutFirstIndent()
|
||||
val indentType = if (settings.kotlinCustomSettings.CONTINUATION_INDENT_FOR_CHAINED_CALLS)
|
||||
Indent.Type.CONTINUATION
|
||||
else
|
||||
Indent.getNormalIndent()
|
||||
Indent.Type.NORMAL
|
||||
val isNonFirstChainedCall = operationBlockIndex > 0 && isCallBlock(nodeSubBlocks[operationBlockIndex - 1])
|
||||
val indent = Indent.getIndent(indentType, false,
|
||||
isNonFirstChainedCall && hasLineBreakBefore(nodeSubBlocks[operationBlockIndex - 1]))
|
||||
val wrap = if ((settings.kotlinCommonSettings.WRAP_FIRST_METHOD_IN_CALL_CHAIN || isNonFirstChainedCall) &&
|
||||
canWrapCallChain(node))
|
||||
Wrap.createWrap(settings.kotlinCommonSettings.METHOD_CALL_CHAIN_WRAP, true)
|
||||
@@ -545,6 +549,21 @@ fun needWrapArgumentList(psi: PsiElement): Boolean {
|
||||
return args?.singleOrNull()?.getArgumentExpression() !is KtObjectLiteralExpression
|
||||
}
|
||||
|
||||
private fun hasLineBreakBefore(block: ASTBlock): Boolean {
|
||||
val topLevelParent = block.node.parents().firstOrNull {
|
||||
it.treeParent.elementType == KtNodeTypes.BLOCK || it.treeParent.elementType == KtStubElementTypes.FILE
|
||||
} ?: return false
|
||||
for (leaf in block.node.leaves(forward = false)) {
|
||||
if (leaf.textContains('\n')) {
|
||||
return true
|
||||
}
|
||||
if (leaf.textRange.startOffset == topLevelParent.startOffset) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun NodeIndentStrategy.PositionStrategy.continuationIf(
|
||||
option: (KotlinCodeStyleSettings) -> Boolean,
|
||||
indentFirst: Boolean = false
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fun test() {
|
||||
Single.just(Object())
|
||||
.map {
|
||||
it
|
||||
}.map {
|
||||
it // The code unexpectedly shifts to the left
|
||||
}
|
||||
}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
fun test() {
|
||||
Single.just(Object())
|
||||
.map {
|
||||
it
|
||||
}.map {
|
||||
it // The code unexpectedly shifts to the left
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
val ret = (DB.Article innerJoin DB.Project).slice(DB.Article.project, DB.Article.project.count()).select {
|
||||
filterBlogs(params)
|
||||
}.groupBy(DB.Article.project).map {
|
||||
val count = it[DB.Article.project.count()]
|
||||
val project = it[DB.Article.team.count()]
|
||||
}
|
||||
filterBlogs(params)
|
||||
}.groupBy(DB.Article.project).map {
|
||||
val count = it[DB.Article.project.count()]
|
||||
val project = it[DB.Article.team.count()]
|
||||
}
|
||||
Reference in New Issue
Block a user