Option to apply normal indent to children of 'if' expressions
This commit is contained in:
+1
@@ -45,6 +45,7 @@ public class KotlinCodeStyleSettings extends CustomCodeStyleSettings {
|
|||||||
public boolean CONTINUATION_INDENT_FOR_EXPRESSION_BODIES = true;
|
public boolean CONTINUATION_INDENT_FOR_EXPRESSION_BODIES = true;
|
||||||
public boolean CONTINUATION_INDENT_FOR_CHAINED_CALLS = true;
|
public boolean CONTINUATION_INDENT_FOR_CHAINED_CALLS = true;
|
||||||
public boolean CONTINUATION_INDENT_IN_SUPERTYPE_LISTS = true;
|
public boolean CONTINUATION_INDENT_IN_SUPERTYPE_LISTS = true;
|
||||||
|
public boolean CONTINUATION_INDENT_IN_IF_CONDITIONS = true;
|
||||||
public int BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES = 0;
|
public int BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES = 0;
|
||||||
public int WRAP_EXPRESSION_BODY_FUNCTIONS = 0;
|
public int WRAP_EXPRESSION_BODY_FUNCTIONS = 0;
|
||||||
public int WRAP_ELVIS_EXPRESSIONS = 1;
|
public int WRAP_ELVIS_EXPRESSIONS = 1;
|
||||||
|
|||||||
@@ -358,12 +358,32 @@ abstract class KotlinCommonBlock(
|
|||||||
val childrenAlignmentStrategy = getChildrenAlignmentStrategy()
|
val childrenAlignmentStrategy = getChildrenAlignmentStrategy()
|
||||||
val wrappingStrategy = getWrappingStrategy()
|
val wrappingStrategy = getWrappingStrategy()
|
||||||
|
|
||||||
return node.children()
|
val childNodes = if (node.elementType == KtNodeTypes.BINARY_EXPRESSION) {
|
||||||
|
val binaryExpressionChildren = mutableListOf<ASTNode>()
|
||||||
|
collectBinaryExpressionChildren(node, binaryExpressionChildren)
|
||||||
|
binaryExpressionChildren.asSequence()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.children()
|
||||||
|
}
|
||||||
|
|
||||||
|
return childNodes
|
||||||
.filter { it.textRange.length > 0 && it.elementType != TokenType.WHITE_SPACE }
|
.filter { it.textRange.length > 0 && it.elementType != TokenType.WHITE_SPACE }
|
||||||
.map { buildSubBlock(it, childrenAlignmentStrategy, wrappingStrategy ) }
|
.map { buildSubBlock(it, childrenAlignmentStrategy, wrappingStrategy ) }
|
||||||
.toList()
|
.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun collectBinaryExpressionChildren(node: ASTNode, result: MutableList<ASTNode>) {
|
||||||
|
for (child in node.children()) {
|
||||||
|
if (child.elementType == KtNodeTypes.BINARY_EXPRESSION) {
|
||||||
|
collectBinaryExpressionChildren(child, result)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.add(child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getWrappingStrategy(): WrappingStrategy {
|
private fun getWrappingStrategy(): WrappingStrategy {
|
||||||
val commonSettings = settings.kotlinCommonSettings
|
val commonSettings = settings.kotlinCommonSettings
|
||||||
val elementType = node.elementType
|
val elementType = node.elementType
|
||||||
@@ -574,6 +594,16 @@ private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
|
|||||||
}
|
}
|
||||||
.continuationIf(KotlinCodeStyleSettings::CONTINUATION_INDENT_FOR_EXPRESSION_BODIES, indentFirst = true),
|
.continuationIf(KotlinCodeStyleSettings::CONTINUATION_INDENT_FOR_EXPRESSION_BODIES, indentFirst = true),
|
||||||
|
|
||||||
|
strategy("If condition")
|
||||||
|
.within(KtNodeTypes.CONDITION)
|
||||||
|
.set { settings ->
|
||||||
|
val indentType = if (settings.kotlinCustomSettings.CONTINUATION_INDENT_IN_IF_CONDITIONS)
|
||||||
|
Indent.Type.CONTINUATION
|
||||||
|
else
|
||||||
|
Indent.Type.NORMAL
|
||||||
|
Indent.getIndent(indentType, false, true)
|
||||||
|
},
|
||||||
|
|
||||||
strategy("Property accessor expression body")
|
strategy("Property accessor expression body")
|
||||||
.within(KtNodeTypes.PROPERTY_ACCESSOR)
|
.within(KtNodeTypes.PROPERTY_ACCESSOR)
|
||||||
.forElement {
|
.forElement {
|
||||||
@@ -614,6 +644,7 @@ private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
|
|||||||
|
|
||||||
strategy("Binary expressions")
|
strategy("Binary expressions")
|
||||||
.within(BINARY_EXPRESSIONS)
|
.within(BINARY_EXPRESSIONS)
|
||||||
|
.forElement { node -> !node.suppressBinaryExpressionIndent() }
|
||||||
.set(Indent.getContinuationWithoutFirstIndent(false)),
|
.set(Indent.getContinuationWithoutFirstIndent(false)),
|
||||||
|
|
||||||
strategy("Parenthesized expression")
|
strategy("Parenthesized expression")
|
||||||
@@ -678,6 +709,18 @@ private fun hasErrorElementBefore(node: ASTNode): Boolean {
|
|||||||
return lastChild?.elementType == TokenType.ERROR_ELEMENT
|
return lastChild?.elementType == TokenType.ERROR_ELEMENT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suppress indent for binary expressions when there is a block higher in the tree that forces
|
||||||
|
* its indent to children ('if' condition or elvis).
|
||||||
|
*/
|
||||||
|
private fun ASTNode.suppressBinaryExpressionIndent(): Boolean {
|
||||||
|
var psi = psi.parent as? KtBinaryExpression ?: return false
|
||||||
|
while (psi.parent is KtBinaryExpression) {
|
||||||
|
psi = psi.parent as KtBinaryExpression
|
||||||
|
}
|
||||||
|
return psi.parent?.node?.elementType == KtNodeTypes.CONDITION || psi.operationToken == KtTokens.ELVIS
|
||||||
|
}
|
||||||
|
|
||||||
private fun getAlignmentForChildInParenthesis(
|
private fun getAlignmentForChildInParenthesis(
|
||||||
shouldAlignChild: Boolean, parameter: IElementType, delimiter: IElementType,
|
shouldAlignChild: Boolean, parameter: IElementType, delimiter: IElementType,
|
||||||
shouldAlignParenthesis: Boolean, openBracket: IElementType, closeBracket: IElementType): CommonAlignmentStrategy {
|
shouldAlignParenthesis: Boolean, openBracket: IElementType, closeBracket: IElementType): CommonAlignmentStrategy {
|
||||||
|
|||||||
+9
@@ -40,6 +40,10 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
|
|||||||
is Number -> 0
|
is Number -> 0
|
||||||
else -> 1
|
else -> 1
|
||||||
}
|
}
|
||||||
|
if (i2 > 0 &&
|
||||||
|
i3 < 0) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
private fun foo2():Int {
|
private fun foo2():Int {
|
||||||
@@ -307,6 +311,11 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
|
|||||||
"Elvis expressions",
|
"Elvis expressions",
|
||||||
options = *arrayOf(CodeStyleSettingsCustomizable.WRAP_OPTIONS_FOR_SINGLETON, CodeStyleSettingsCustomizable.WRAP_VALUES_FOR_SINGLETON)
|
options = *arrayOf(CodeStyleSettingsCustomizable.WRAP_OPTIONS_FOR_SINGLETON, CodeStyleSettingsCustomizable.WRAP_VALUES_FOR_SINGLETON)
|
||||||
)
|
)
|
||||||
|
showCustomOption(
|
||||||
|
KotlinCodeStyleSettings::CONTINUATION_INDENT_IN_IF_CONDITIONS,
|
||||||
|
"Use continuation indent in conditions",
|
||||||
|
CodeStyleSettingsCustomizable.WRAPPING_IF_STATEMENT
|
||||||
|
)
|
||||||
}
|
}
|
||||||
LanguageCodeStyleSettingsProvider.SettingsType.BLANK_LINES_SETTINGS -> {
|
LanguageCodeStyleSettingsProvider.SettingsType.BLANK_LINES_SETTINGS -> {
|
||||||
consumer.showStandardOptions(
|
consumer.showStandardOptions(
|
||||||
|
|||||||
+3
-4
@@ -2,9 +2,9 @@ fun test() {
|
|||||||
val somelong = 1 + 2 +
|
val somelong = 1 + 2 +
|
||||||
3 - 4 -
|
3 - 4 -
|
||||||
5 * 6 *
|
5 * 6 *
|
||||||
7 / 8 /
|
7 / 8 /
|
||||||
9 % 10 %
|
9 % 10 %
|
||||||
11
|
11
|
||||||
|
|
||||||
val withBrackets = 3 +
|
val withBrackets = 3 +
|
||||||
4 - (5 +
|
4 - (5 +
|
||||||
@@ -12,4 +12,3 @@ fun test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
|
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
|
||||||
// Strage behaviour for disabled alignment is same to Java
|
|
||||||
|
|||||||
@@ -12,4 +12,3 @@ fun test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
|
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
|
||||||
// Strage behaviour for disabled alignment is same to Java
|
|
||||||
|
|||||||
@@ -12,4 +12,3 @@ fun test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
|
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
|
||||||
// Strage behaviour for disabled alignment is same to Java
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fun foo() {
|
||||||
|
if ("abc" > "def" &&
|
||||||
|
"qqq" < "bbb" &&
|
||||||
|
"ddd" > "efg") {
|
||||||
|
println("foo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
if (
|
||||||
|
"abc" > "def" &&
|
||||||
|
"qqq" < "bbb" &&
|
||||||
|
"ddd" > "efg") {
|
||||||
|
println("foo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SET_TRUE: CONTINUATION_INDENT_IN_IF_CONDITIONS
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
fun foo() {
|
||||||
|
if ("abc" > "def" &&
|
||||||
|
"qqq" < "bbb" &&
|
||||||
|
"ddd" > "efg") {
|
||||||
|
println("foo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
if (
|
||||||
|
"abc" > "def" &&
|
||||||
|
"qqq" < "bbb" &&
|
||||||
|
"ddd" > "efg") {
|
||||||
|
println("foo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SET_TRUE: CONTINUATION_INDENT_IN_IF_CONDITIONS
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
fun foo() {
|
||||||
|
if ("abc" > "def" &&
|
||||||
|
"qqq" < "bbb" &&
|
||||||
|
"ddd" > "efg") {
|
||||||
|
println("foo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
if (
|
||||||
|
"abc" > "def" &&
|
||||||
|
"qqq" < "bbb" &&
|
||||||
|
"ddd" > "efg") {
|
||||||
|
println("foo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SET_TRUE: CONTINUATION_INDENT_IN_IF_CONDITIONS
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fun foo(b: Boolean) {
|
fun foo(b: Boolean) {
|
||||||
if (// comment 1
|
if (// comment 1
|
||||||
b) 1 // comment 2
|
b) 1 // comment 2
|
||||||
else 2
|
else 2
|
||||||
}
|
}
|
||||||
@@ -470,6 +470,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("IfConditionIndent.after.kt")
|
||||||
|
public void testIfConditionIndent() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/IfConditionIndent.after.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("IfElseRemoveLineBreak.after.kt")
|
@TestMetadata("IfElseRemoveLineBreak.after.kt")
|
||||||
public void testIfElseRemoveLineBreak() throws Exception {
|
public void testIfElseRemoveLineBreak() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/IfElseRemoveLineBreak.after.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/IfElseRemoveLineBreak.after.kt");
|
||||||
@@ -1316,6 +1322,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest {
|
|||||||
doTestInverted(fileName);
|
doTestInverted(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("IfConditionIndent.after.inv.kt")
|
||||||
|
public void testIfConditionIndent() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/IfConditionIndent.after.inv.kt");
|
||||||
|
doTestInverted(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("IfElseWithTrickyComments.after.inv.kt")
|
@TestMetadata("IfElseWithTrickyComments.after.inv.kt")
|
||||||
public void testIfElseWithTrickyComments() throws Exception {
|
public void testIfElseWithTrickyComments() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/IfElseWithTrickyComments.after.inv.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/IfElseWithTrickyComments.after.inv.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user