Skip to content

Commit

Permalink
Add an extendedIndentForExpressionBodies flag to the `WRONG_INDENTA…
Browse files Browse the repository at this point in the history
…TION` check (#1443)

### What's done:

 * This commit adds a separate `extendedIndentForExpressionBodies` flag,
   defaulting to `false`.
 * The flag controls whether continuation indent is used to indent expression
   bodies (previously, controlled with `extendedIndentAfterOperators`).
 * The corresponding flags are:
   * _IDEA_: `CONTINUATION_INDENT_FOR_EXPRESSION_BODIES`
   * `.editorconfig`: `ij_kotlin_continuation_indent_for_expression_bodies`
  • Loading branch information
0x6675636b796f75676974687562 authored Jul 13, 2022
1 parent ad8718b commit 81cb1b1
Show file tree
Hide file tree
Showing 17 changed files with 178 additions and 87 deletions.
6 changes: 6 additions & 0 deletions diktat-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
extendedIndentOfParameters: false
# If true: if first parameter in parameter list is on the same line as opening parenthesis, then other parameters can be aligned with it
alignedParameters: true
# If true, expression bodies which begin on a separate line are indented
# using a continuation indent. The default is false.
#
# This flag is called CONTINUATION_INDENT_FOR_EXPRESSION_BODIES in IDEA and
# ij_kotlin_continuation_indent_for_expression_bodies in .editorconfig.
extendedIndentForExpressionBodies: false
# If true: if expression is split by newline after operator like +/-/`*`, then the next line is indented with two indentations instead of one
extendedIndentAfterOperators: false
# If true: when dot qualified expression starts on a new line, this line will be indented with two indentations instead of one
Expand Down
1 change: 1 addition & 0 deletions diktat-common/src/test/resources/test-rules-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
newlineAtEnd: true
extendedIndentOfParameters: false
alignedParameters: true
extendedIndentForExpressionBodies: false
extendedIndentAfterOperators: false
indentationSize: 4
- name: EMPTY_BLOCK_STRUCTURE_ERROR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings

/**
* Performs the following check: assignment operator increases indent by one step for the expression after it.
* If [IndentationConfig.extendedIndentAfterOperators] is set to true, indentation is increased by two steps instead.
* If [IndentationConfig.extendedIndentForExpressionBodies] is set to `true`, indentation is increased by two steps instead.
*/
internal class AssignmentOperatorChecker(configuration: IndentationConfig) : CustomIndentationChecker(configuration) {
override fun checkNode(whiteSpace: PsiWhiteSpace, indentError: IndentationError): CheckResult? {
val prevNode = whiteSpace.prevSibling?.node
if (prevNode?.elementType == EQ && prevNode.treeNext.let { it.elementType == WHITE_SPACE && it.textContains('\n') }) {
return CheckResult.from(indentError.actual, (whiteSpace.parentIndent()
?: indentError.expected) + (if (configuration.extendedIndentAfterOperators) 2 else 1) * configuration.indentationSize, true)
?: indentError.expected) + (if (configuration.extendedIndentForExpressionBodies) 2 else 1) * configuration.indentationSize, true)
}
return null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,46 @@ internal class IndentationConfig(config: Map<String, String>) : RuleConfiguratio
*/
val alignedParameters = config["alignedParameters"]?.toBoolean() ?: true

/**
* If `true`, expression bodies which begin on a separate line are indented
* using a _continuation indent_. The flag is **off**:
*
* ```kotlin
* val a: Boolean =
* false
*
* val b: Boolean
* get() =
* false
*
* fun f(): Boolean =
* false
* ```
*
* The flag is **on**:
*
* ```kotlin
* val a: Boolean =
* false
*
* val b: Boolean
* get() =
* false
*
* fun f(): Boolean =
* false
* ```
*
* The default is `false`.
*
* This flag is called `CONTINUATION_INDENT_FOR_EXPRESSION_BODIES` in _IDEA_
* and `ij_kotlin_continuation_indent_for_expression_bodies` in
* `.editorconfig`.
*
* @since 1.2.2
*/
val extendedIndentForExpressionBodies = config["extendedIndentForExpressionBodies"]?.toBoolean() ?: false

/**
* If true, if expression is split by newline after operator like +/-/`*`, then the next line is indented with two indentations instead of one
*/
Expand Down
6 changes: 6 additions & 0 deletions diktat-rules/src/main/resources/diktat-analysis-huawei.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@
extendedIndentOfParameters: false
# If true: if first parameter in parameter list is on the same line as opening parenthesis, then other parameters can be aligned with it
alignedParameters: true
# If true, expression bodies which begin on a separate line are indented
# using a continuation indent. The default is false.
#
# This flag is called CONTINUATION_INDENT_FOR_EXPRESSION_BODIES in IDEA and
# ij_kotlin_continuation_indent_for_expression_bodies in .editorconfig.
extendedIndentForExpressionBodies: false
# If true: if expression is split by newline after operator like +/-/`*`, then the next line is indented with two indentations instead of one
extendedIndentAfterOperators: false
# If true: when dot qualified expression starts on a new line, this line will be indented with two indentations instead of one
Expand Down
6 changes: 6 additions & 0 deletions diktat-rules/src/main/resources/diktat-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@
extendedIndentOfParameters: false
# If true: if first parameter in parameter list is on the same line as opening parenthesis, then other parameters can be aligned with it
alignedParameters: true
# If true, expression bodies which begin on a separate line are indented
# using a continuation indent. The default is false.
#
# This flag is called CONTINUATION_INDENT_FOR_EXPRESSION_BODIES in IDEA and
# ij_kotlin_continuation_indent_for_expression_bodies in .editorconfig.
extendedIndentForExpressionBodies: false
# If true: if expression is split by newline after operator like +/-/`*`, then the next line is indented with two indentations instead of one
extendedIndentAfterOperators: false
# The indentation size for each file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation",
"newlineAtEnd" to "true", // expected file should have two newlines at end in order to be read by BufferedReader correctly
"extendedIndentOfParameters" to "true",
"alignedParameters" to "true",
"extendedIndentForExpressionBodies" to "true",
"extendedIndentAfterOperators" to "true",
"extendedIndentBeforeDot" to "true",
)
Expand Down Expand Up @@ -120,29 +121,29 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation",
@Nested
@TestMethodOrder(DisplayName::class)
inner class `Expression body functions` {
@ParameterizedTest(name = "extendedIndentAfterOperators = {0}")
@ParameterizedTest(name = "extendedIndentForExpressionBodies = {0}")
@ValueSource(booleans = [false, true])
@Tag(WarningNames.WRONG_INDENTATION)
fun `should remain unchanged if properly indented`(extendedIndentAfterOperators: Boolean, @TempDir tempDir: Path) {
fun `should remain unchanged if properly indented`(extendedIndentForExpressionBodies: Boolean, @TempDir tempDir: Path) {
val defaultConfig = IndentationConfig("newlineAtEnd" to false)
val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators)
val customConfig = defaultConfig.withCustomParameters("extendedIndentForExpressionBodies" to extendedIndentForExpressionBodies)

lintMultipleMethods(
expressionBodyFunctions[extendedIndentAfterOperators].assertNotNull(),
expressionBodyFunctions[extendedIndentForExpressionBodies].assertNotNull(),
tempDir = tempDir,
rulesConfigList = customConfig.asRulesConfigList())
}

@ParameterizedTest(name = "extendedIndentAfterOperators = {0}")
@ParameterizedTest(name = "extendedIndentForExpressionBodies = {0}")
@ValueSource(booleans = [false, true])
@Tag(WarningNames.WRONG_INDENTATION)
fun `should be reformatted if mis-indented`(extendedIndentAfterOperators: Boolean, @TempDir tempDir: Path) {
fun `should be reformatted if mis-indented`(extendedIndentForExpressionBodies: Boolean, @TempDir tempDir: Path) {
val defaultConfig = IndentationConfig("newlineAtEnd" to false)
val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators)
val customConfig = defaultConfig.withCustomParameters("extendedIndentForExpressionBodies" to extendedIndentForExpressionBodies)

lintMultipleMethods(
actualContent = expressionBodyFunctions[!extendedIndentAfterOperators].assertNotNull(),
expectedContent = expressionBodyFunctions[extendedIndentAfterOperators].assertNotNull(),
actualContent = expressionBodyFunctions[!extendedIndentForExpressionBodies].assertNotNull(),
expectedContent = expressionBodyFunctions[extendedIndentForExpressionBodies].assertNotNull(),
tempDir = tempDir,
rulesConfigList = customConfig.asRulesConfigList())
}
Expand Down Expand Up @@ -222,29 +223,29 @@ class IndentationRuleFixTest : FixTestBase("test/paragraph3/indentation",
@Nested
@TestMethodOrder(DisplayName::class)
inner class `Parentheses-surrounded infix expressions` {
@ParameterizedTest(name = "extendedIndentAfterOperators = {0}")
@ParameterizedTest(name = "extendedIndentForExpressionBodies = {0}")
@ValueSource(booleans = [false, true])
@Tag(WarningNames.WRONG_INDENTATION)
fun `should be properly indented`(extendedIndentAfterOperators: Boolean, @TempDir tempDir: Path) {
fun `should be properly indented`(extendedIndentForExpressionBodies: Boolean, @TempDir tempDir: Path) {
val defaultConfig = IndentationConfig("newlineAtEnd" to false)
val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators)
val customConfig = defaultConfig.withCustomParameters("extendedIndentForExpressionBodies" to extendedIndentForExpressionBodies)

lintMultipleMethods(
parenthesesSurroundedInfixExpressions[extendedIndentAfterOperators].assertNotNull(),
parenthesesSurroundedInfixExpressions[extendedIndentForExpressionBodies].assertNotNull(),
tempDir = tempDir,
rulesConfigList = customConfig.asRulesConfigList())
}

@ParameterizedTest(name = "extendedIndentAfterOperators = {0}")
@ParameterizedTest(name = "extendedIndentForExpressionBodies = {0}")
@ValueSource(booleans = [false, true])
@Tag(WarningNames.WRONG_INDENTATION)
fun `should be reformatted if mis-indented`(extendedIndentAfterOperators: Boolean, @TempDir tempDir: Path) {
fun `should be reformatted if mis-indented`(extendedIndentForExpressionBodies: Boolean, @TempDir tempDir: Path) {
val defaultConfig = IndentationConfig("newlineAtEnd" to false)
val customConfig = defaultConfig.withCustomParameters("extendedIndentAfterOperators" to extendedIndentAfterOperators)
val customConfig = defaultConfig.withCustomParameters("extendedIndentForExpressionBodies" to extendedIndentForExpressionBodies)

lintMultipleMethods(
actualContent = parenthesesSurroundedInfixExpressions[!extendedIndentAfterOperators].assertNotNull(),
expectedContent = parenthesesSurroundedInfixExpressions[extendedIndentAfterOperators].assertNotNull(),
actualContent = parenthesesSurroundedInfixExpressions[!extendedIndentForExpressionBodies].assertNotNull(),
expectedContent = parenthesesSurroundedInfixExpressions[extendedIndentForExpressionBodies].assertNotNull(),
tempDir = tempDir,
rulesConfigList = customConfig.asRulesConfigList())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal object IndentationRuleTestMixin {
"indentationSize" to "$indentationSize",
"newlineAtEnd" to "$newlineAtEnd",
"extendedIndentOfParameters" to "$extendedIndentOfParameters",
"extendedIndentForExpressionBodies" to "$extendedIndentForExpressionBodies",
"extendedIndentAfterOperators" to "$extendedIndentAfterOperators",
"extendedIndentBeforeDot" to "$extendedIndentBeforeDot",
).apply {
Expand Down Expand Up @@ -68,6 +69,7 @@ internal object IndentationRuleTestMixin {
fun extendedIndent(enabled: Boolean): Array<Pair<String, Any>> =
arrayOf(
"extendedIndentOfParameters" to enabled,
"extendedIndentForExpressionBodies" to enabled,
"extendedIndentAfterOperators" to enabled,
"extendedIndentBeforeDot" to enabled)

Expand Down
Loading

0 comments on commit 81cb1b1

Please sign in to comment.