-
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.
* Wrapper in kts file ### What's done: Created new rule, added tests and documentation
- Loading branch information
Showing
15 changed files
with
303 additions
and
3 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
80 changes: 80 additions & 0 deletions
80
diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/RunInScript.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,80 @@ | ||
package org.cqfn.diktat.ruleset.rules.chapter6 | ||
|
||
import org.cqfn.diktat.common.config.rules.RulesConfig | ||
import org.cqfn.diktat.ruleset.constants.EmitType | ||
import org.cqfn.diktat.ruleset.constants.Warnings.RUN_IN_SCRIPT | ||
import org.cqfn.diktat.ruleset.utils.* | ||
|
||
import com.pinterest.ktlint.core.Rule | ||
import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION | ||
import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION | ||
import com.pinterest.ktlint.core.ast.ElementType.LAMBDA_ARGUMENT | ||
import com.pinterest.ktlint.core.ast.ElementType.LAMBDA_EXPRESSION | ||
import com.pinterest.ktlint.core.ast.ElementType.PARENTHESIZED | ||
import com.pinterest.ktlint.core.ast.ElementType.SCRIPT_INITIALIZER | ||
import com.pinterest.ktlint.core.ast.ElementType.VALUE_ARGUMENT | ||
import com.pinterest.ktlint.core.ast.ElementType.VALUE_ARGUMENT_LIST | ||
import org.jetbrains.kotlin.com.intellij.lang.ASTNode | ||
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement | ||
|
||
/** | ||
* Rule that checks if kts script contains other functions except run code | ||
* In .kts files allow use only property declaration, function, classes, and code inside `run` block | ||
* In gradle.kts files allow to call expression and dot qualified expression in addition to everything used in .kts files | ||
*/ | ||
class RunInScript(private val configRules: List<RulesConfig>) : Rule("run-script") { | ||
private var isFixMode: Boolean = false | ||
private lateinit var emitWarn: EmitType | ||
|
||
override fun visit( | ||
node: ASTNode, | ||
autoCorrect: Boolean, | ||
emit: EmitType | ||
) { | ||
isFixMode = autoCorrect | ||
emitWarn = emit | ||
|
||
if (node.elementType == SCRIPT_INITIALIZER && node.getRootNode().getFilePath().isKotlinScript()) { | ||
if (node.getRootNode().getFilePath().isGradleScript()) { | ||
checkGradleNode(node) | ||
} else { | ||
checkScript(node) | ||
} | ||
} | ||
} | ||
|
||
private fun checkGradleNode(node: ASTNode) { | ||
val astNode = if (node.firstChildNode.elementType == PARENTHESIZED) { | ||
node.firstChildNode | ||
} else { | ||
node | ||
} | ||
if (!astNode.hasChildOfType(CALL_EXPRESSION) && !astNode.hasChildOfType(DOT_QUALIFIED_EXPRESSION)) { | ||
RUN_IN_SCRIPT.warnAndFix(configRules, emitWarn, isFixMode, astNode.text, astNode.startOffset, astNode) { | ||
val parent = astNode.treeParent | ||
val newNode = KotlinParser().createNode("run {\n ${astNode.text}\n} \n") | ||
val newScript = CompositeElement(SCRIPT_INITIALIZER) | ||
parent.addChild(newScript, astNode) | ||
newScript.addChild(newNode) | ||
parent.removeChild(astNode) | ||
} | ||
} | ||
} | ||
|
||
private fun checkScript(node: ASTNode) { | ||
val isLambdaArgument = node.firstChildNode.hasChildOfType(LAMBDA_ARGUMENT) | ||
val isLambdaInsideValueArgument = node.firstChildNode.findChildByType(VALUE_ARGUMENT_LIST)?.findChildByType(VALUE_ARGUMENT)?.findChildByType(LAMBDA_EXPRESSION) != null | ||
if (!(isLambdaArgument || isLambdaInsideValueArgument)) { | ||
RUN_IN_SCRIPT.warnAndFix(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) { | ||
if (node.firstChildNode.elementType != DOT_QUALIFIED_EXPRESSION) { | ||
val parent = node.treeParent | ||
val newNode = KotlinParser().createNode("run {\n ${node.text}\n} \n") | ||
val newScript = CompositeElement(SCRIPT_INITIALIZER) | ||
parent.addChild(newScript, node) | ||
newScript.addChild(newNode) | ||
parent.removeChild(node) | ||
} | ||
} | ||
} | ||
} | ||
} |
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
16 changes: 16 additions & 0 deletions
16
diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/RunInScriptFixTest.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,16 @@ | ||
package org.cqfn.diktat.ruleset.chapter6 | ||
|
||
import org.cqfn.diktat.ruleset.rules.chapter6.RunInScript | ||
import org.cqfn.diktat.util.FixTestBase | ||
|
||
import generated.WarningNames | ||
import org.junit.jupiter.api.Tag | ||
import org.junit.jupiter.api.Test | ||
|
||
class RunInScriptFixTest : FixTestBase("test/chapter6/script", ::RunInScript) { | ||
@Test | ||
@Tag(WarningNames.RUN_IN_SCRIPT) | ||
fun `should wrap into run`() { | ||
fixAndCompare("SimpleRunInScriptExpected.kts", "SimpleRunInScriptTest.kts") | ||
} | ||
} |
133 changes: 133 additions & 0 deletions
133
diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/RunInScriptWarnTest.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,133 @@ | ||
package org.cqfn.diktat.ruleset.chapter6 | ||
|
||
import org.cqfn.diktat.ruleset.constants.Warnings.RUN_IN_SCRIPT | ||
import org.cqfn.diktat.ruleset.rules.DIKTAT_RULE_SET_ID | ||
import org.cqfn.diktat.ruleset.rules.chapter6.RunInScript | ||
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 RunInScriptWarnTest : LintTestBase(::RunInScript) { | ||
private val ruleId: String = "$DIKTAT_RULE_SET_ID:run-script" | ||
|
||
@Test | ||
@Tag(WarningNames.RUN_IN_SCRIPT) | ||
fun `check simple example`() { | ||
lintMethod( | ||
""" | ||
class A {} | ||
fun foo() { | ||
} | ||
diktat {} | ||
diktat({}) | ||
foo/*df*/() | ||
foo( //dfdg | ||
10 | ||
) | ||
println("hello") | ||
w.map { it -> it } | ||
tasks.register("a") { | ||
dependsOn("b") | ||
doFirst { | ||
generateCodeStyle(file("rootDir/guide"), file("rootDir/../wp")) | ||
} | ||
} | ||
""".trimMargin(), | ||
LintError(10, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} foo/*df*/()", true), | ||
LintError(12, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} foo( //dfdg...", true), | ||
LintError(15, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} println(\"hello\")", true), | ||
LintError(17, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} w.map { it -> it }", true), | ||
LintError(19, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} tasks.register(\"a\") {...", true), | ||
fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.RUN_IN_SCRIPT) | ||
fun `check correct examples`() { | ||
lintMethod( | ||
""" | ||
run { | ||
println("hello") | ||
} | ||
run{println("hello")} | ||
val task = tasks.register("a") { | ||
} | ||
""".trimMargin(), | ||
fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.RUN_IN_SCRIPT) | ||
fun `check correct with custom wrapper`() { | ||
lintMethod( | ||
""" | ||
custom { | ||
println("hello") | ||
} | ||
oneMore{println("hello")} | ||
another { | ||
println("hello") | ||
} | ||
""".trimMargin(), | ||
fileName = "src/main/kotlin/org/cqfn/diktat/Example.kts" | ||
) | ||
} | ||
|
||
@Test | ||
@Tag(WarningNames.RUN_IN_SCRIPT) | ||
fun `check gradle file`() { | ||
lintMethod( | ||
""" | ||
class A {} | ||
fun foo() { | ||
} | ||
if(true) { | ||
goo() | ||
} | ||
diktat {} | ||
diktat({}) | ||
foo/*df*/() | ||
foo( //dfdg | ||
10 | ||
) | ||
println("hello") | ||
w.map { it -> it } | ||
(tasks.register("a") { | ||
dependsOn("b") | ||
doFirst { | ||
generateCodeStyle(file("rootDir/guide"), file("rootDir/../wp")) | ||
} | ||
}) | ||
""".trimMargin(), | ||
LintError(6, 17, ruleId, "${RUN_IN_SCRIPT.warnText()} if(true) {...", true), | ||
fileName = "src/main/kotlin/org/cqfn/diktat/builds.gradle.kts" | ||
) | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
diktat-rules/src/test/resources/test/chapter6/script/SimpleRunInScriptExpected.kts
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 @@ | ||
|
||
run { | ||
println("hello world!") | ||
} | ||
|
||
fun foo() { | ||
println() | ||
} | ||
|
||
val q = Config() | ||
|
||
run { | ||
println("a") | ||
} | ||
|
||
also { | ||
println("a") | ||
} |
16 changes: 16 additions & 0 deletions
16
diktat-rules/src/test/resources/test/chapter6/script/SimpleRunInScriptTest.kts
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,16 @@ | ||
|
||
println("hello world!") | ||
|
||
fun foo() { | ||
println() | ||
} | ||
|
||
val q = Config() | ||
|
||
run { | ||
println("a") | ||
} | ||
|
||
also { | ||
println("a") | ||
} |
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
517e3d6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't able to retrieve PDD puzzles from the code base and submit them to GitHub. If you think that it's a bug on our side, please submit it to yegor256/0pdd:
Please, copy and paste this stack trace to GitHub: