-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Suggest using lastIndex instead of length - 1 for strings (#1221)
* Change property length with operation - 1 to property lastIndex ### What's done: - Added new rule to replace ".length - 1" to ".lastIndex" - Added warn tests - Added fix tests - Updated Readme (rule 6.2.4) (#1140) Co-authored-by: Alexey Votintsev <alexeyvotintsev.yandex.ru>
- Loading branch information
Showing
14 changed files
with
385 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/UseLastIndex.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package org.cqfn.diktat.ruleset.rules.chapter6 | ||
|
||
import org.cqfn.diktat.common.config.rules.RulesConfig | ||
import org.cqfn.diktat.ruleset.constants.Warnings | ||
import org.cqfn.diktat.ruleset.rules.DiktatRule | ||
import org.cqfn.diktat.ruleset.utils.* | ||
|
||
import com.pinterest.ktlint.core.ast.ElementType.BINARY_EXPRESSION | ||
import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION | ||
import com.pinterest.ktlint.core.ast.ElementType.INTEGER_CONSTANT | ||
import com.pinterest.ktlint.core.ast.ElementType.OPERATION_REFERENCE | ||
import com.pinterest.ktlint.core.ast.ElementType.REFERENCE_EXPRESSION | ||
import com.pinterest.ktlint.core.ast.children | ||
import org.jetbrains.kotlin.com.intellij.lang.ASTNode | ||
|
||
/** | ||
* This rule checks if there use property length with operation - 1 and fix this on lastIndex | ||
*/ | ||
class UseLastIndex(configRules: List<RulesConfig>) : DiktatRule( | ||
"last-index", | ||
configRules, | ||
listOf(Warnings.USE_LAST_INDEX) | ||
) { | ||
override fun logic(node: ASTNode) { | ||
if (node.elementType == BINARY_EXPRESSION) { | ||
changeRight(node) | ||
} | ||
} | ||
|
||
private fun changeRight(node: ASTNode) { | ||
val listWithRightLength = node.children().filter { | ||
val operation = node.getFirstChildWithType(OPERATION_REFERENCE) | ||
val number = node.getFirstChildWithType(INTEGER_CONSTANT) | ||
it.elementType == DOT_QUALIFIED_EXPRESSION && it.lastChildNode.text == "length" && it.lastChildNode.elementType == REFERENCE_EXPRESSION && | ||
operation?.text == "-" && number?.text == "1" | ||
} | ||
if (listWithRightLength.toList().isNotEmpty()) { | ||
Warnings.USE_LAST_INDEX.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { | ||
fix(node) | ||
} | ||
} | ||
} | ||
|
||
private fun fix(node: ASTNode) { | ||
// A.B.length - 1 -> A.B | ||
val text = node.firstChildNode.text.replace("length", "lastIndex") | ||
val parent = node.treeParent | ||
val textParent = parent.text.replace(node.text, text) | ||
val newParent = KotlinParser().createNode(textParent) | ||
parent.treeParent.replaceChild(parent, newParent) | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/UseLastIndexFixTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.cqfn.diktat.ruleset.chapter6 | ||
|
||
import org.cqfn.diktat.ruleset.rules.chapter6.UseLastIndex | ||
import org.cqfn.diktat.util.FixTestBase | ||
|
||
import org.junit.jupiter.api.Test | ||
|
||
class UseLastIndexFixTest : FixTestBase("test/chapter6/lastIndex_change", ::UseLastIndex) { | ||
@Test | ||
fun `fix example with white spaces`() { | ||
fixAndCompare("UseAnyWhiteSpacesExpected.kt", "UseAnyWhiteSpacesTest.kt") | ||
} | ||
|
||
@Test | ||
fun `fix example with incorrect use length`() { | ||
fixAndCompare("IncorrectUseLengthMinusOneExpected.kt", "IncorrectUseLengthMinusOneTest.kt") | ||
} | ||
} |
101 changes: 101 additions & 0 deletions
101
diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/UseLastIndexWarnTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package org.cqfn.diktat.ruleset.chapter6 | ||
|
||
import org.cqfn.diktat.ruleset.constants.Warnings | ||
import org.cqfn.diktat.ruleset.rules.DIKTAT_RULE_SET_ID | ||
import org.cqfn.diktat.ruleset.rules.chapter6.UseLastIndex | ||
import org.cqfn.diktat.util.LintTestBase | ||
|
||
import com.pinterest.ktlint.core.LintError | ||
import generated.WarningNames | ||
import org.junit.jupiter.api.Tag | ||
import org.junit.jupiter.api.Test | ||
|
||
class UseLastIndexWarnTest : LintTestBase(::UseLastIndex) { | ||
private val ruleId = "$DIKTAT_RULE_SET_ID:last-index" | ||
|
||
@Test | ||
@Tag(WarningNames.USE_LAST_INDEX) | ||
fun `find method Length - 1 with many dot expressions`() { | ||
lintMethod( | ||
""" | ||
|val A = "AAAAAAAA" | ||
|val D = A.B.C.length - 1 | ||
| | ||
""".trimMargin(), | ||
LintError(2, 9, ruleId, "${Warnings.USE_LAST_INDEX.warnText()} A.B.C.length - 1", true) | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.USE_LAST_INDEX) | ||
fun `find method Length - 1 for mane line`() { | ||
lintMethod( | ||
""" | ||
|fun foo() { | ||
| val A : String = "AAAA" | ||
| var B = A.length | ||
| - | ||
| 1 | ||
|} | ||
""".trimMargin() | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.USE_LAST_INDEX) | ||
fun `find method Length - 1 with many spaces and tabulation`() { | ||
lintMethod( | ||
""" | ||
|val A : String = "AAAA" | ||
|var B = A.length - 1 + 214 | ||
|var C = A.length - 19 | ||
| | ||
""".trimMargin(), | ||
LintError(2, 12, ruleId, "${Warnings.USE_LAST_INDEX.warnText() } A.length - 1", true) | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.USE_LAST_INDEX) | ||
fun `find method Length - 1 without spaces`() { | ||
lintMethod( | ||
""" | ||
|val A : String = "AAAA" | ||
|var B = A.length-1 | ||
| | ||
""".trimMargin(), | ||
LintError(2, 9, ruleId, "${Warnings.USE_LAST_INDEX.warnText()} A.length-1", true) | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.USE_LAST_INDEX) | ||
fun `find method Length - 1 without length`() { | ||
lintMethod( | ||
""" | ||
|val A = "AAAA" | ||
|val B = -1 | ||
|val C = 6 + 121 | ||
|var D = B + C | ||
|var E = A.length + 1 | ||
""".trimMargin() | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.USE_LAST_INDEX) | ||
fun `find method Length - 1 without -1`() { | ||
lintMethod( | ||
""" | ||
|val A = "AAAA" | ||
|val B = -1 | ||
|val C = 6 + 4 | ||
|val D = "AAAA".length - 1 | ||
| | ||
|val M = "ASDFG".length | ||
| | ||
""".trimMargin(), | ||
LintError(4, 9, ruleId, "${Warnings.USE_LAST_INDEX.warnText()} \"AAAA\".length - 1", true) | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
...s/src/test/resources/test/chapter6/lastIndex_change/IncorrectUseLengthMinusOneExpected.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package test.chapter6.lastIndex_change | ||
|
||
fun main(args: Array<String>) { | ||
|
||
val str = "ASDFG" | ||
val A = str.lastIndex | ||
val B = str.lastIndex | ||
|
||
} |
9 changes: 9 additions & 0 deletions
9
...rules/src/test/resources/test/chapter6/lastIndex_change/IncorrectUseLengthMinusOneTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package test.chapter6.lastIndex_change | ||
|
||
fun main(args: Array<String>) { | ||
|
||
val str = "ASDFG" | ||
val A = str.length - 1 | ||
val B = str.length - 1 | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
diktat-rules/src/test/resources/test/chapter6/lastIndex_change/UseAnyWhiteSpacesExpected.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package test.chapter6.lastIndex_change | ||
|
||
fun main(args: Array<String>) { | ||
val str = "ASDFG" | ||
val A = str.lastIndex | ||
val B = str.lastIndex | ||
val C = str.lastIndex | ||
val D = str.lastIndex | ||
val F = str.lastIndex | ||
val E = str[str.lastIndex] | ||
val G = str[str.lastIndex ] | ||
} |
12 changes: 12 additions & 0 deletions
12
diktat-rules/src/test/resources/test/chapter6/lastIndex_change/UseAnyWhiteSpacesTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package test.chapter6.lastIndex_change | ||
|
||
fun main(args: Array<String>) { | ||
val str = "ASDFG" | ||
val A = str.length - 1 | ||
val B = str.length-1 | ||
val C = str.length -1 | ||
val D = str.length- 1 | ||
val F = str.length - 1 | ||
val E = str[str.length - 1] | ||
val G = str[str.length - 1 ] | ||
} |
Oops, something went wrong.