-
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.
### What's done: * Added rule logic * Added new warning * Added new test
- Loading branch information
1 parent
241f45e
commit feef0d8
Showing
12 changed files
with
239 additions
and
4 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
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
66 changes: 66 additions & 0 deletions
66
diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/LambdaLengthRule.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,66 @@ | ||
package org.cqfn.diktat.ruleset.rules | ||
|
||
import org.cqfn.diktat.common.config.rules.RuleConfiguration | ||
import org.cqfn.diktat.common.config.rules.RulesConfig | ||
import org.cqfn.diktat.common.config.rules.getRuleConfig | ||
import org.cqfn.diktat.ruleset.constants.EmitType | ||
import org.cqfn.diktat.ruleset.constants.Warnings | ||
import org.cqfn.diktat.ruleset.utils.* | ||
|
||
import com.pinterest.ktlint.core.Rule | ||
import com.pinterest.ktlint.core.ast.ElementType | ||
import com.pinterest.ktlint.core.ast.isPartOfComment | ||
import org.jetbrains.kotlin.com.intellij.lang.ASTNode | ||
|
||
/** | ||
* Rule 5.2.4 check lambda length without parameters | ||
*/ | ||
class LambdaLengthRule(private val configRules: List<RulesConfig>) : Rule("lambda-length") { | ||
private var isFixMode: Boolean = false | ||
private lateinit var emitWarn: EmitType | ||
|
||
override fun visit( | ||
node: ASTNode, | ||
autoCorrect: Boolean, | ||
emit: EmitType | ||
) { | ||
emitWarn = emit | ||
isFixMode = autoCorrect | ||
|
||
val configuration by lazy { | ||
LambdaLengthConfiguration( | ||
configRules.getRuleConfig(Warnings.TOO_MANY_LINES_IN_LAMBDA)?.configuration ?: emptyMap() | ||
) | ||
} | ||
|
||
if (node.elementType == ElementType.LAMBDA_EXPRESSION) { | ||
checkLambda(node, configuration) | ||
} | ||
} | ||
|
||
private fun checkLambda(node: ASTNode, configuration: LambdaLengthConfiguration) { | ||
val copyNode = node.clone() as ASTNode | ||
val isIt: Boolean = node.findAllNodesWithSpecificType(ElementType.REFERENCE_EXPRESSION).map {re -> re.text}.indexOf("it") != -1 | ||
val parameters = node.findChildByType(ElementType.FUNCTION_LITERAL)?.findChildByType(ElementType.VALUE_PARAMETER_LIST) | ||
val sizeLambda = countCodeLines(copyNode) | ||
if (parameters == null && isIt && sizeLambda > configuration.maxLambdaLength) { | ||
Warnings.TOO_MANY_LINES_IN_LAMBDA.warn(configRules, emitWarn, isFixMode, | ||
"max length lambda without arguments is ${configuration.maxLambdaLength}, but you have $sizeLambda", | ||
node.startOffset, node) | ||
} | ||
} | ||
|
||
/** | ||
* [RuleConfiguration] for lambda length | ||
*/ | ||
class LambdaLengthConfiguration(config: Map<String, String>) : RuleConfiguration(config) { | ||
/** | ||
* Maximum allowed lambda length | ||
*/ | ||
val maxLambdaLength = config["maxLambdaLength"]?.toLong() ?: MAX_LINES_IN_LAMBDA | ||
} | ||
|
||
companion object { | ||
private const val MAX_LINES_IN_LAMBDA = 10L | ||
} | ||
} |
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
141 changes: 141 additions & 0 deletions
141
diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter5/LambdaLengthWarnTest.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,141 @@ | ||
package org.cqfn.diktat.ruleset.chapter5 | ||
|
||
import org.cqfn.diktat.common.config.rules.RulesConfig | ||
import org.cqfn.diktat.ruleset.constants.Warnings | ||
import org.cqfn.diktat.ruleset.rules.DIKTAT_RULE_SET_ID | ||
import org.cqfn.diktat.ruleset.rules.LambdaLengthRule | ||
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 LambdaLengthWarnTest : LintTestBase(::LambdaLengthRule) { | ||
private val ruleId = "$DIKTAT_RULE_SET_ID:lambda-length" | ||
private val rulesConfigList: List<RulesConfig> = listOf( | ||
RulesConfig( | ||
Warnings.TOO_MANY_LINES_IN_LAMBDA.name, true, | ||
mapOf("maxLambdaLength" to "3")) | ||
) | ||
|
||
@Test | ||
@Tag(WarningNames.TOO_MANY_LINES_IN_LAMBDA) | ||
fun `less than max`() { | ||
lintMethod( | ||
""" | ||
|fun foo() { | ||
| val x = 10 | ||
| val list = listOf(1, 2, 3, 4, 5) | ||
| .map {element -> element + x} | ||
|} | ||
""".trimMargin(), | ||
rulesConfigList = rulesConfigList | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.TOO_MANY_LINES_IN_LAMBDA) | ||
fun `less than max without argument`() { | ||
lintMethod( | ||
""" | ||
|fun foo() { | ||
| val x = 10 | ||
| val list = listOf(1, 2, 3, 4, 5) | ||
| .map {it + x} | ||
|} | ||
""".trimMargin(), | ||
rulesConfigList = rulesConfigList | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.TOO_MANY_LINES_IN_LAMBDA) | ||
fun `more than max with argument`() { | ||
lintMethod( | ||
""" | ||
|fun foo() { | ||
| val calculateX = { x : Int -> | ||
| when(x) { | ||
| in 0..40 -> "Fail" | ||
| in 41..70 -> "Pass" | ||
| in 71..100 -> "Distinction" | ||
| else -> false | ||
| } | ||
| } | ||
|} | ||
""".trimMargin(), | ||
rulesConfigList = rulesConfigList | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.TOO_MANY_LINES_IN_LAMBDA) | ||
fun `more than maximum without argument`() { | ||
lintMethod( | ||
""" | ||
|fun foo() { | ||
| val list = listOf(1, 2, 3, 4, 5) | ||
| .map { | ||
| val x = 0 | ||
| val y = x + 1 | ||
| val z = y + 1 | ||
| it + z | ||
| | ||
| | ||
| | ||
| | ||
| } | ||
|} | ||
""".trimMargin(), | ||
LintError(3, 13, ruleId, "${Warnings.TOO_MANY_LINES_IN_LAMBDA.warnText()} max length lambda without arguments is 3, but you have 6", false), | ||
rulesConfigList = rulesConfigList | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.TOO_MANY_LINES_IN_LAMBDA) | ||
fun `two lambda more than maximum without argument`() { | ||
lintMethod( | ||
""" | ||
|fun foo() { | ||
| val list = listOf(1, 2, 3, 4, 5) | ||
| .filter { n -> n % 2 == 1 } | ||
| .map { | ||
| val x = 0 | ||
| val y = x + 1 | ||
| val z = y + 1 | ||
| it + z | ||
| | ||
| | ||
| | ||
| | ||
| } | ||
|} | ||
""".trimMargin(), | ||
LintError(4, 13, ruleId, "${Warnings.TOO_MANY_LINES_IN_LAMBDA.warnText()} max length lambda without arguments is 3, but you have 6", false), | ||
rulesConfigList = rulesConfigList | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.TOO_MANY_LINES_IN_LAMBDA) | ||
fun `lambda in lambda`() { | ||
lintMethod( | ||
""" | ||
|fun foo() { | ||
| val list = listOf(listOf(1,2,3), listOf(4,5,6)) | ||
| .map {l -> l.map { | ||
| val x = 0 | ||
| val y = x + 1 | ||
| val z = y + 1 | ||
| println(it) | ||
| } | ||
| } | ||
| } | ||
""".trimMargin(), | ||
LintError(3, 25, ruleId, "${Warnings.TOO_MANY_LINES_IN_LAMBDA.warnText()} max length lambda without arguments is 3, but you have 6", false), | ||
rulesConfigList = rulesConfigList | ||
) | ||
} | ||
} |
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