Option to apply normal indent to children of 'if' expressions

This commit is contained in:
Dmitry Jemerov
2017-12-13 16:29:27 +01:00
parent 640bf22e4f
commit 79a509df7b
11 changed files with 124 additions and 8 deletions
@@ -45,6 +45,7 @@ public class KotlinCodeStyleSettings extends CustomCodeStyleSettings {
public boolean CONTINUATION_INDENT_FOR_EXPRESSION_BODIES = true;
public boolean CONTINUATION_INDENT_FOR_CHAINED_CALLS = 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 WRAP_EXPRESSION_BODY_FUNCTIONS = 0;
public int WRAP_ELVIS_EXPRESSIONS = 1;
@@ -358,12 +358,32 @@ abstract class KotlinCommonBlock(
val childrenAlignmentStrategy = getChildrenAlignmentStrategy()
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 }
.map { buildSubBlock(it, childrenAlignmentStrategy, wrappingStrategy ) }
.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 {
val commonSettings = settings.kotlinCommonSettings
val elementType = node.elementType
@@ -574,6 +594,16 @@ private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
}
.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")
.within(KtNodeTypes.PROPERTY_ACCESSOR)
.forElement {
@@ -614,6 +644,7 @@ private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
strategy("Binary expressions")
.within(BINARY_EXPRESSIONS)
.forElement { node -> !node.suppressBinaryExpressionIndent() }
.set(Indent.getContinuationWithoutFirstIndent(false)),
strategy("Parenthesized expression")
@@ -678,6 +709,18 @@ private fun hasErrorElementBefore(node: ASTNode): Boolean {
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(
shouldAlignChild: Boolean, parameter: IElementType, delimiter: IElementType,
shouldAlignParenthesis: Boolean, openBracket: IElementType, closeBracket: IElementType): CommonAlignmentStrategy {
@@ -40,6 +40,10 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
is Number -> 0
else -> 1
}
if (i2 > 0 &&
i3 < 0) {
return 2
}
return 0
}
private fun foo2():Int {
@@ -307,6 +311,11 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
"Elvis expressions",
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 -> {
consumer.showStandardOptions(
+3 -4
View File
@@ -2,9 +2,9 @@ fun test() {
val somelong = 1 + 2 +
3 - 4 -
5 * 6 *
7 / 8 /
9 % 10 %
11
7 / 8 /
9 % 10 %
11
val withBrackets = 3 +
4 - (5 +
@@ -12,4 +12,3 @@ fun test() {
}
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
// Strage behaviour for disabled alignment is same to Java
-1
View File
@@ -12,4 +12,3 @@ fun test() {
}
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
// Strage behaviour for disabled alignment is same to Java
-1
View File
@@ -12,4 +12,3 @@ fun test() {
}
// SET_TRUE: ALIGN_MULTILINE_BINARY_OPERATION
// Strage behaviour for disabled alignment is same to Java
+18
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
if (// comment 1
b) 1 // comment 2
b) 1 // comment 2
else 2
}
@@ -470,6 +470,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest {
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")
public void testIfElseRemoveLineBreak() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/IfElseRemoveLineBreak.after.kt");
@@ -1316,6 +1322,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest {
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")
public void testIfElseWithTrickyComments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/IfElseWithTrickyComments.after.inv.kt");