Skip to content

Commit

Permalink
Merge branch 'detekt:main' into remove-naming-multyrule
Browse files Browse the repository at this point in the history
  • Loading branch information
VovaStelmashchuk committed Sep 7, 2022
2 parents 1871aac + c1178f2 commit 5e74730
Show file tree
Hide file tree
Showing 19 changed files with 416 additions and 26 deletions.
4 changes: 3 additions & 1 deletion build-logic/src/main/kotlin/releasing.gradle.kts
Expand Up @@ -38,7 +38,9 @@ project.afterEvaluate {
files(
cliBuildDir.resolve("libs/detekt-cli-${project.version}-all.jar"),
cliBuildDir.resolve("distributions/detekt-cli-${project.version}.zip"),
project(":detekt-formatting").buildDir.resolve("libs/detekt-formatting-${project.version}.jar")
project(":detekt-formatting").buildDir.resolve("libs/detekt-formatting-${project.version}.jar"),
project(":detekt-rules-ruleauthors").buildDir
.resolve("libs/detekt-rules-ruleauthors-${project.version}.jar")
)
)
}
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Expand Up @@ -27,6 +27,7 @@ allprojects {
dependencies {
detekt(project(":detekt-cli"))
detektPlugins(project(":detekt-formatting"))
detektPlugins(project(":detekt-rules-ruleauthors"))
}

tasks.withType<Detekt>().configureEach {
Expand Down
4 changes: 0 additions & 4 deletions detekt-api/build.gradle.kts
Expand Up @@ -35,10 +35,6 @@ tasks.dokkaHtml {
notCompatibleWithConfigurationCache("https://github.com/Kotlin/dokka/issues/1217")
}

tasks.apiDump {
notCompatibleWithConfigurationCache("https://github.com/Kotlin/binary-compatibility-validator/issues/95")
}

apiValidation {
ignoredPackages.add("io.gitlab.arturbosch.detekt.api.internal")
}
2 changes: 2 additions & 0 deletions detekt-core/src/main/resources/default-detekt-config.yml
Expand Up @@ -391,6 +391,8 @@ performance:
SpreadOperator:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
UnnecessaryPartOfBinaryExpression:
active: false
UnnecessaryTemporaryInstantiation:
active: true

Expand Down
10 changes: 9 additions & 1 deletion detekt-generator/build.gradle.kts
Expand Up @@ -22,6 +22,8 @@ val configDir = "${rootProject.rootDir}/detekt-core/src/main/resources"
val cliOptionsFile = "${rootProject.rootDir}/website/docs/gettingstarted/_cli-options.md"
val defaultConfigFile = "$configDir/default-detekt-config.yml"
val deprecationFile = "$configDir/deprecation.properties"
val formattingConfigFile = "${rootProject.rootDir}/detekt-formatting/src/main/resources/config/config.yml"
val ruleauthorsConfigFile = "${rootProject.rootDir}/detekt-rules-ruleauthors/src/main/resources/config/config.yml"

val ruleModules = rootProject.subprojects
.filter { "rules" in it.name }
Expand All @@ -36,13 +38,16 @@ val generateDocumentation by tasks.registering(JavaExec::class) {

inputs.files(
ruleModules.map { fileTree(it) },
fileTree("${rootProject.rootDir}/detekt-rules-ruleauthors/src/main/kotlin"),
fileTree("${rootProject.rootDir}/detekt-formatting/src/main/kotlin"),
file("${rootProject.rootDir}/detekt-generator/build/libs/detekt-generator-${Versions.DETEKT}-all.jar"),
)

outputs.files(
fileTree(documentationDir),
file(defaultConfigFile),
file(formattingConfigFile),
file(ruleauthorsConfigFile),
file(deprecationFile),
file(cliOptionsFile),
)
Expand All @@ -55,7 +60,10 @@ val generateDocumentation by tasks.registering(JavaExec::class) {
mainClass.set("io.gitlab.arturbosch.detekt.generator.Main")
args = listOf(
"--input",
ruleModules.plus("${rootProject.rootDir}/detekt-formatting/src/main/kotlin").joinToString(","),
ruleModules
.plus("${rootProject.rootDir}/detekt-rules-ruleauthors/src/main/kotlin")
.plus("${rootProject.rootDir}/detekt-formatting/src/main/kotlin")
.joinToString(","),
"--documentation",
documentationDir,
"--config",
Expand Down
Expand Up @@ -24,7 +24,7 @@ class DetektPrinter(private val arguments: GeneratorArgs) {
}
}
yamlWriter.write(arguments.configPath, "default-detekt-config") {
ConfigPrinter.print(pages.filterNot { it.ruleSet.name == "formatting" })
ConfigPrinter.print(pages.filterNot { it.ruleSet.name == "formatting" || it.ruleSet.name == "ruleauthors" })
}
propertiesWriter.write(arguments.configPath, "deprecation") {
// We intentionally not filter for "formatting" as we want to be able to deprecate
Expand All @@ -36,6 +36,11 @@ class DetektPrinter(private val arguments: GeneratorArgs) {
printRuleSetPage(pages.first { it.ruleSet.name == "formatting" })
}
}
yamlWriter.write(Paths.get("../detekt-rules-ruleauthors/src/main/resources/config"), "config") {
yaml {
printRuleSetPage(pages.first { it.ruleSet.name == "ruleauthors" })
}
}
}

private fun markdownHeader(ruleSet: String): String {
Expand Down
4 changes: 0 additions & 4 deletions detekt-psi-utils/build.gradle.kts
Expand Up @@ -10,10 +10,6 @@ dependencies {
testImplementation(projects.detektTest)
}

tasks.apiDump {
notCompatibleWithConfigurationCache("https://github.com/Kotlin/binary-compatibility-validator/issues/95")
}

apiValidation {
ignoredPackages.add("io.github.detekt.psi.internal")
}
Expand Up @@ -20,7 +20,8 @@ class PerformanceProvider : DefaultRuleSetProvider {
SpreadOperator(config),
UnnecessaryTemporaryInstantiation(config),
ArrayPrimitive(config),
CouldBeSequence(config)
CouldBeSequence(config),
UnnecessaryPartOfBinaryExpression(config),
)
)
}
@@ -0,0 +1,92 @@
package io.gitlab.arturbosch.detekt.rules.performance

import io.gitlab.arturbosch.detekt.api.CodeSmell
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Debt
import io.gitlab.arturbosch.detekt.api.Entity
import io.gitlab.arturbosch.detekt.api.Issue
import io.gitlab.arturbosch.detekt.api.Rule
import io.gitlab.arturbosch.detekt.api.Severity
import org.jetbrains.kotlin.com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression

/**
* Unnecessary binary expression add complexity to the code and accomplish nothing. They should be removed.
* The rule works with all binary expression included if and when condition. The rule also works with all predicates.
* The rule verify binary expression only in case when the expression use only one type of the following
* operators || or &&.
*
* <noncompliant>
* val foo = true
* val bar = true
*
* if (foo || bar || foo) {
* }
* </noncompliant>
*
* <compliant>
* val foo = true
* if (foo) {
* }
* </compliant>
*
*/
class UnnecessaryPartOfBinaryExpression(config: Config = Config.empty) : Rule(config) {

override val issue: Issue = Issue(
"UnnecessaryPartOfBinaryExpression",
Severity.Performance,
"Detects duplicate condition into binary expression and recommends to remove unnecessary checks",
Debt.FIVE_MINS
)

override fun visitBinaryExpression(expression: KtBinaryExpression) {
super.visitBinaryExpression(expression)
if (expression.parent is KtBinaryExpression) {
return
}

val isOrOr = expression.getAllOperations().all { it != KtTokens.OROR }
val isAndAnd = expression.getAllOperations().all { it != KtTokens.ANDAND }

if (isOrOr || isAndAnd) {
val allChildren = expression.getAllVariables().map { it.text.replace(Regex("\\s"), "") }

if (allChildren != allChildren.distinct()) {
report(CodeSmell(issue, Entity.from(expression), issue.description))
}
}
}

private fun KtBinaryExpression.getAllVariables(): List<KtElement> {
return buildList {
addAll(this@getAllVariables.left?.getVariable().orEmpty())
addAll(this@getAllVariables.right?.getVariable().orEmpty())
}
}

private fun KtExpression.getVariable(): List<KtElement> {
return if (this is KtBinaryExpression &&
(this.operationToken == KtTokens.OROR || this.operationToken == KtTokens.ANDAND)
) {
this.getAllVariables()
} else {
listOf(this)
}
}

private fun KtBinaryExpression.getAllOperations(): List<IElementType> {
return buildList {
(this@getAllOperations.left as? KtBinaryExpression)?.let {
addAll(it.getAllOperations())
}
(this@getAllOperations.right as? KtBinaryExpression)?.let {
addAll(it.getAllOperations())
}
add(this@getAllOperations.operationToken)
}
}
}

0 comments on commit 5e74730

Please sign in to comment.