Skip to content

Commit

Permalink
Simplify the code by implementing IndentationConfigAware
Browse files Browse the repository at this point in the history
### What's done:

 * Now, `CustomIndentationChecker` implements `IndentationConfigAware`.
  • Loading branch information
0x6675636b796f75676974687562 committed Jul 22, 2022
1 parent b59fe91 commit 73365d4
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,113 @@ internal interface IndentationConfigAware {
operator fun Int.minus(amount: IndentationAmount): Int =
unindent(level = amount.level())

/**
* Allows the `+` operation between an Int and an IndentationAmount to be
* commutative. Now, the following are equivalent:
*
* ```kotlin
* val i = 42 + IndentationAmount.SINGLE
* val j = IndentationAmount.SINGLE + 42
* ```
*
* — as are these:
*
* ```kotlin
* val i = 42 + IndentationAmount.SINGLE
* val j = IndentationAmount.SINGLE + 42
* ```
*
* @receiver the indentation amount.
* @param indentationSpaces the indentation level (in space characters).
* @return the new (increased) indentation level.
* @see IndentationAmount.minus
*/
operator fun IndentationAmount.plus(indentationSpaces: Int): Int =
indentationSpaces + this

/**
* Allows expressions like this:
*
* ```kotlin
* 42 - IndentationAmount.SINGLE + 4
* ```
*
* to be rewritten this way:
*
* ```kotlin
* 42 - (IndentationAmount.SINGLE - 4)
* ```
*
* @receiver the indentation amount.
* @param indentationSpaces the indentation level (in space characters).
* @return the new (decreased) indentation level.
* @see IndentationAmount.plus
*/
operator fun IndentationAmount.minus(indentationSpaces: Int): Int =
this + (-indentationSpaces)

/**
* @receiver the 1st term.
* @param other the 2nd term.
* @return the two indentation amounts combined, as the indentation level
* (in space characters).
* @see IndentationAmount.minus
*/
operator fun IndentationAmount.plus(other: IndentationAmount): Int =
this + (+other)

/**
* @receiver the minuend.
* @param other the subtrahend.
* @return one amount subtracted from the other, as the indentation level
* (in space characters).
* @see IndentationAmount.plus
*/
operator fun IndentationAmount.minus(other: IndentationAmount): Int =
this + (-other)

/**
* @receiver the indentation amount.
* @return the indentation level (in space characters).
* @see IndentationAmount.unaryMinus
*/
operator fun IndentationAmount.unaryPlus(): Int =
level() * configuration.indentationSize

/**
* @receiver the indentation amount.
* @return the negated indentation level (in space characters).
* @see IndentationAmount.unaryPlus
*/
operator fun IndentationAmount.unaryMinus(): Int =
-(+this)

companion object Factory {
/**
* Creates a new instance.
*
* While you may call this function directly, consider using
* [withIndentationConfig] instead.
*
* @param configuration the configuration this instance will wrap.
* @return the newly created instance.
* @see withIndentationConfig
*/
operator fun invoke(configuration: IndentationConfig): IndentationConfigAware =
object : IndentationConfigAware {
override val configuration = configuration
}

/**
* Calls the specified function [block] with [IndentationConfigAware] as
* its receiver and returns its result.
*
* @param configuration the indentation configuration.
* @param block the function block to call.
* @return the result returned by the function block.
*/
inline fun <T> withIndentationConfig(configuration: IndentationConfig,
block: IndentationConfigAware.() -> T): T =
with(IndentationConfigAware(configuration), block)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_INDENTATION
import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationAmount.NONE
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationAmount.SINGLE
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationConfigAware.Factory.withIndentationConfig
import org.cqfn.diktat.ruleset.utils.NEWLINE
import org.cqfn.diktat.ruleset.utils.SPACE
import org.cqfn.diktat.ruleset.utils.TAB
Expand Down Expand Up @@ -395,14 +396,14 @@ class IndentationRule(configRules: List<RulesConfig>) : DiktatRule(
return
}

with(IndentationConfigAware(configuration)) {
withIndentationConfig(configuration) {
/*
* A `REGULAR_STRING_PART`.
*/
val regularStringPart = templateEntry.firstChildNode as LeafPsiElement
val regularStringPartText = regularStringPart.checkRegularStringPart().text
// shift of the node depending on its initial string template indentation
val nodeStartIndent = (regularStringPartText.leadingSpaceCount() - actualIndentation).unindent().zeroIfNegative()
val nodeStartIndent = (regularStringPartText.leadingSpaceCount() - actualIndentation - SINGLE).zeroIfNegative()

val isPrevStringTemplate = templateEntry.treePrev.elementType in stringLiteralTokens
val isNextStringTemplate = templateEntry.treeNext.elementType in stringLiteralTokens
Expand All @@ -417,7 +418,7 @@ class IndentationRule(configRules: List<RulesConfig>) : DiktatRule(

// if string template is after literal_string
// or if there is no string template in literal_string
else -> (expectedIndentation.indent() + nodeStartIndent).spaces + regularStringPartText.trimStart()
else -> (expectedIndentation + SINGLE + nodeStartIndent).spaces + regularStringPartText.trimStart()
}

regularStringPart.rawReplaceWithText(correctedText)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
package org.cqfn.diktat.ruleset.utils.indentation

import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationAmount
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationConfigAware
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationAmount.SINGLE
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationError
import org.cqfn.diktat.ruleset.utils.hasParent
import org.cqfn.diktat.ruleset.utils.lastIndent
Expand Down Expand Up @@ -66,7 +66,7 @@ internal class AssignmentOperatorChecker(configuration: IndentationConfig) : Cus
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.extendedIndentForExpressionBodies) 2 else 1) * configuration.indentationSize, true)
?: indentError.expected) + IndentationAmount.valueOf(configuration.extendedIndentForExpressionBodies), true)
}
return null
}
Expand Down Expand Up @@ -121,7 +121,7 @@ internal class ValueParameterListChecker(configuration: IndentationConfig) : Cus
}
.let { (_, line) -> line.substringBefore(parameterAfterLpar.text).length }
} else if (configuration.extendedIndentOfParameters) {
indentError.expected + configuration.indentationSize
indentError.expected + SINGLE
} else {
indentError.expected
}
Expand All @@ -137,16 +137,14 @@ internal class ValueParameterListChecker(configuration: IndentationConfig) : Cus
*/
internal class ExpressionIndentationChecker(configuration: IndentationConfig) : CustomIndentationChecker(configuration) {
override fun checkNode(whiteSpace: PsiWhiteSpace, indentError: IndentationError): CheckResult? =
with(IndentationConfigAware(configuration)) {
when {
whiteSpace.parent.node.elementType == BINARY_EXPRESSION && whiteSpace.prevSibling.node.elementType == OPERATION_REFERENCE -> {
val parentIndent = whiteSpace.parentIndent() ?: indentError.expected
val expectedIndent = parentIndent + IndentationAmount.valueOf(configuration.extendedIndentAfterOperators)
CheckResult.from(indentError.actual, expectedIndent, true)
}

else -> null
when {
whiteSpace.parent.node.elementType == BINARY_EXPRESSION && whiteSpace.prevSibling.node.elementType == OPERATION_REFERENCE -> {
val parentIndent = whiteSpace.parentIndent() ?: indentError.expected
val expectedIndent = parentIndent + IndentationAmount.valueOf(configuration.extendedIndentAfterOperators)
CheckResult.from(indentError.actual, expectedIndent, true)
}

else -> null
}
}

Expand Down Expand Up @@ -176,10 +174,10 @@ internal class SuperTypeListChecker(config: IndentationConfig) : CustomIndentati
.treePrev
.takeIf { it.elementType == WHITE_SPACE }
?.textContains('\n') ?: false
val expectedIndent = indentError.expected + (if (hasNewlineBeforeColon) 2 else 1) * configuration.indentationSize
val expectedIndent = indentError.expected + IndentationAmount.valueOf(extendedIndent = hasNewlineBeforeColon)
return CheckResult.from(indentError.actual, expectedIndent)
} else if (whiteSpace.parent.node.elementType == SUPER_TYPE_LIST) {
val expectedIndent = whiteSpace.parentIndent() ?: (indentError.expected + configuration.indentationSize)
val expectedIndent = whiteSpace.parentIndent() ?: (indentError.expected + SINGLE)
return CheckResult.from(indentError.actual, expectedIndent)
}
return null
Expand Down Expand Up @@ -219,7 +217,7 @@ internal class DotCallChecker(config: IndentationConfig) : CustomIndentationChec
} || nextNode.isCommentBeforeDot()) && whiteSpace.parents.none { it.node.elementType == LONG_STRING_TEMPLATE_ENTRY }
}
?.let { node ->
val indentIncrement = (if (configuration.extendedIndentBeforeDot) 2 else 1) * configuration.indentationSize
val indentIncrement = IndentationAmount.valueOf(configuration.extendedIndentBeforeDot)
if (node.isFromStringTemplate()) {
return CheckResult.from(indentError.actual, indentError.expected +
indentIncrement, true)
Expand Down Expand Up @@ -266,7 +264,7 @@ internal class ConditionalsAndLoopsWithoutBracesChecker(config: IndentationConfi
}
.takeIf { it }
?.let {
CheckResult.from(indentError.actual, indentError.expected + configuration.indentationSize, true)
CheckResult.from(indentError.actual, indentError.expected + SINGLE, true)
}
}
}
Expand All @@ -279,7 +277,7 @@ internal class CustomGettersAndSettersChecker(config: IndentationConfig) : Custo
val parent = whiteSpace.parent
if (parent is KtProperty && whiteSpace.nextSibling is KtPropertyAccessor) {
return CheckResult.from(indentError.actual, (parent.parentIndent()
?: indentError.expected) + configuration.indentationSize, true)
?: indentError.expected) + SINGLE, true)
}
return null
}
Expand All @@ -293,7 +291,7 @@ internal class ArrowInWhenChecker(configuration: IndentationConfig) : CustomInde
val prevNode = whiteSpace.prevSibling?.node
if (prevNode?.elementType == ARROW && whiteSpace.parent is KtWhenEntry) {
return CheckResult.from(indentError.actual, (whiteSpace.parentIndent()
?: indentError.expected) + configuration.indentationSize, true)
?: indentError.expected) + SINGLE, true)
}
return null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package org.cqfn.diktat.ruleset.utils.indentation

import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationConfigAware
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationError
import org.cqfn.diktat.ruleset.utils.NEWLINE

Expand All @@ -12,7 +13,7 @@ import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace
/**
* @property configuration configuration of indentation rule
*/
internal abstract class CustomIndentationChecker(protected val configuration: IndentationConfig) {
internal abstract class CustomIndentationChecker(override val configuration: IndentationConfig) : IndentationConfigAware {
/**
* This method checks if this white space is an exception from general rule
* If true, checks if it is properly indented and fixes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package org.cqfn.diktat.ruleset.chapter3.spaces

import org.cqfn.diktat.ruleset.chapter3.spaces.IndentationRuleTestMixin.IndentationConfig
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationAmount.EXTENDED
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationAmount.NONE
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationAmount.SINGLE
import org.cqfn.diktat.ruleset.rules.chapter3.files.IndentationConfigAware.Factory.withIndentationConfig

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.MethodOrderer.DisplayName
import org.junit.jupiter.api.TestMethodOrder
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource

@TestMethodOrder(DisplayName::class)
class IndentationConfigAwareTest {
@ParameterizedTest(name = "indentationSize = {0}")
@ValueSource(ints = [2, 4, 8])
fun `Int + IndentationAmount`(indentationSize: Int) {
val config = IndentationConfig("indentationSize" to indentationSize)

withIndentationConfig(config) {
assertThat(42 + NONE).isEqualTo(42)
assertThat(42 + SINGLE).isEqualTo(42 + indentationSize)
assertThat(42 + EXTENDED).isEqualTo(42 + 2 * indentationSize)
}
}

@ParameterizedTest(name = "indentationSize = {0}")
@ValueSource(ints = [2, 4, 8])
fun `Int - IndentationAmount`(indentationSize: Int) {
val config = IndentationConfig("indentationSize" to indentationSize)

withIndentationConfig(config) {
assertThat(42 - NONE).isEqualTo(42)
assertThat(42 - SINGLE).isEqualTo(42 - indentationSize)
assertThat(42 - EXTENDED).isEqualTo(42 - 2 * indentationSize)
}
}

@ParameterizedTest(name = "indentationSize = {0}")
@ValueSource(ints = [2, 4, 8])
fun `IndentationAmount + Int`(indentationSize: Int) {
val config = IndentationConfig("indentationSize" to indentationSize)

withIndentationConfig(config) {
assertThat(NONE + 42).isEqualTo(42 + NONE)
assertThat(SINGLE + 42).isEqualTo(42 + SINGLE)
assertThat(EXTENDED + 42).isEqualTo(42 + EXTENDED)

assertThat(42 + (SINGLE + 2)).isEqualTo((42 + SINGLE) + 2)
}
}

@ParameterizedTest(name = "indentationSize = {0}")
@ValueSource(ints = [2, 4, 8])
fun `IndentationAmount - Int`(indentationSize: Int) {
val config = IndentationConfig("indentationSize" to indentationSize)

withIndentationConfig(config) {
assertThat(NONE - 42).isEqualTo(-(42 - NONE))
assertThat(SINGLE - 42).isEqualTo(-(42 - SINGLE))
assertThat(EXTENDED - 42).isEqualTo(-(42 - EXTENDED))

assertThat(42 - (SINGLE - 2)).isEqualTo(42 - SINGLE + 2)
}
}

@ParameterizedTest(name = "indentationSize = {0}")
@ValueSource(ints = [2, 4, 8])
fun `IndentationAmount + IndentationAmount`(indentationSize: Int) {
val config = IndentationConfig("indentationSize" to indentationSize)

withIndentationConfig(config) {
assertThat(NONE + SINGLE).isEqualTo(0 + SINGLE)
assertThat(SINGLE + SINGLE).isEqualTo(0 + EXTENDED)

assertThat(42 + SINGLE + SINGLE).isEqualTo(42 + EXTENDED)
assertThat(42 + (SINGLE + SINGLE)).isEqualTo(42 + EXTENDED)
}
}

@ParameterizedTest(name = "indentationSize = {0}")
@ValueSource(ints = [2, 4, 8])
fun `IndentationAmount - IndentationAmount`(indentationSize: Int) {
val config = IndentationConfig("indentationSize" to indentationSize)

withIndentationConfig(config) {
assertThat(NONE - SINGLE).isEqualTo(0 - SINGLE)
assertThat(SINGLE - SINGLE).isEqualTo(0)
assertThat(EXTENDED - SINGLE).isEqualTo(0 + SINGLE)
assertThat(NONE - EXTENDED).isEqualTo(0 - EXTENDED)

assertThat(42 + (SINGLE - SINGLE)).isEqualTo(42 + SINGLE - SINGLE)
}
}

@ParameterizedTest(name = "indentationSize = {0}")
@ValueSource(ints = [2, 4, 8])
fun unaryPlus(indentationSize: Int) {
val config = IndentationConfig("indentationSize" to indentationSize)

withIndentationConfig(config) {
assertThat(+NONE).isEqualTo(0)
assertThat(+SINGLE).isEqualTo(indentationSize)
assertThat(+EXTENDED).isEqualTo(2 * indentationSize)

assertThat(EXTENDED - SINGLE).isEqualTo(+SINGLE)
}
}

@ParameterizedTest(name = "indentationSize = {0}")
@ValueSource(ints = [2, 4, 8])
fun unaryMinus(indentationSize: Int) {
val config = IndentationConfig("indentationSize" to indentationSize)

withIndentationConfig(config) {
assertThat(-NONE).isEqualTo(0)
assertThat(-SINGLE).isEqualTo(-indentationSize)
assertThat(-EXTENDED).isEqualTo(-2 * indentationSize)

assertThat(NONE - SINGLE).isEqualTo(-SINGLE)
assertThat(NONE - EXTENDED).isEqualTo(-EXTENDED)
}
}
}
Loading

0 comments on commit 73365d4

Please sign in to comment.