diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 15c73e4905..24f8c24978 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -33,7 +33,7 @@ jobs: java-version: 11 - name: 'Run snapshot action' - uses: mikepenz/gradle-dependency-submission@v0.9.0 + uses: mikepenz/gradle-dependency-submission@v0.9.1 with: use-gradlew: true gradle-build-module: |- diff --git a/README.md b/README.md index e76eadc70c..a335942094 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Main features of diktat are the following: **OR** use `curl`: ```console - $ curl -sSLO https://github.com/saveourtool/diKTat/releases/download/v1.2.5/diktat-1.2.5.jar && chmod a+x diktat + $ curl -sSLO https://github.com/saveourtool/diKTat/releases/download/v1.2.5/diktat-1.2.5.jar && chmod a+x diktat-1.2.5.jar ``` ### Run diKTat diff --git a/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/rules/chapter1/IdentifierNaming.kt b/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/rules/chapter1/IdentifierNaming.kt index fd2f55ea0f..c74031d75d 100644 --- a/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/rules/chapter1/IdentifierNaming.kt +++ b/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/rules/chapter1/IdentifierNaming.kt @@ -35,7 +35,6 @@ import org.jetbrains.kotlin.KtNodeTypes.REFERENCE_EXPRESSION import org.jetbrains.kotlin.KtNodeTypes.TYPE_PARAMETER import org.jetbrains.kotlin.KtNodeTypes.TYPE_REFERENCE import org.jetbrains.kotlin.KtNodeTypes.VALUE_PARAMETER_LIST -import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.com.intellij.psi.tree.TokenSet @@ -403,19 +402,15 @@ class IdentifierNaming(configRules: List) : DiktatRule( } } - // check for methods that return Boolean - val functionReturnType = node.findChildAfter(VALUE_PARAMETER_LIST, TYPE_REFERENCE)?.text - // We don't need to ask subclasses to rename superclass methods if (!node.isOverridden()) { + // check for methods that return Boolean // if function has Boolean return type in 99% of cases it is much better to name it with isXXX or hasXXX prefix @Suppress("COLLAPSE_IF_STATEMENTS") - if (functionReturnType != null && functionReturnType == PrimitiveType.BOOLEAN.typeName.asString()) { - @Suppress("COLLAPSE_IF_STATEMENTS") - if (allMethodPrefixes.none { functionName.text.startsWith(it) }) { - // FixMe: add agressive autofix for this - FUNCTION_BOOLEAN_PREFIX.warn(configRules, emitWarn, functionName.text, functionName.startOffset, functionName) - } + + if (node.hasBooleanReturnType() && !node.isOperatorFun() && allMethodPrefixes.none { functionName.text.startsWith(it) }) { + // FixMe: add agressive autofix for this + FUNCTION_BOOLEAN_PREFIX.warn(configRules, emitWarn, functionName.text, functionName.startOffset, functionName) } } diff --git a/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/utils/AstNodeUtils.kt b/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/utils/AstNodeUtils.kt index 2dd0069bfb..83f84b483f 100644 --- a/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/utils/AstNodeUtils.kt +++ b/diktat-rules/src/main/kotlin/com/saveourtool/diktat/ruleset/utils/AstNodeUtils.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.KtNodeTypes.PARENTHESIZED import org.jetbrains.kotlin.KtNodeTypes.REFERENCE_EXPRESSION import org.jetbrains.kotlin.KtNodeTypes.TYPE_PARAMETER_LIST import org.jetbrains.kotlin.KtNodeTypes.VALUE_PARAMETER_LIST +import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.openapi.util.Key import org.jetbrains.kotlin.com.intellij.psi.PsiElement @@ -183,6 +184,26 @@ fun ASTNode.isAnonymousFunction(): Boolean { return this.getIdentifierName() == null } +/** + * Checks if the function has boolean return type + * + * @return true if the function has boolean return type + */ +fun ASTNode.hasBooleanReturnType(): Boolean { + val functionReturnType = this.findChildAfter(VALUE_PARAMETER_LIST, KtNodeTypes.TYPE_REFERENCE)?.text + return functionReturnType != null && functionReturnType == PrimitiveType.BOOLEAN.typeName.asString() +} + +/** + * Checks if the function is an operator function + * + * @return true if the function is an operator function + */ +fun ASTNode.isOperatorFun(): Boolean { + val modifierListNode = this.findChildByType(MODIFIER_LIST) + return modifierListNode?.hasChildMatching { it.elementType == KtTokens.OPERATOR_KEYWORD } ?: false +} + /** * Checks if the symbols in this node are at the end of line */ diff --git a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter1/IdentifierNamingWarnTest.kt b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter1/IdentifierNamingWarnTest.kt index d32fb24cc7..39352bd853 100644 --- a/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter1/IdentifierNamingWarnTest.kt +++ b/diktat-rules/src/test/kotlin/com/saveourtool/diktat/ruleset/chapter1/IdentifierNamingWarnTest.kt @@ -1,3 +1,7 @@ +@file:Suppress( + "LargeClass" +) + package com.saveourtool.diktat.ruleset.chapter1 import com.saveourtool.diktat.common.config.rules.DIKTAT_RULE_SET_ID @@ -447,6 +451,16 @@ class IdentifierNamingWarnTest : LintTestBase(::IdentifierNaming) { ) } + @Test + @Tag(WarningNames.FUNCTION_BOOLEAN_PREFIX) + fun `fixed false positive result on operator functions`() { + lintMethod( + """ + inline operator fun component3(): Boolean = asDynamic()[2].unsafeCast() + """.trimIndent() + ) + } + @Test @Tag(WarningNames.IDENTIFIER_LENGTH) fun `regression - function argument type`() { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f79eaadae8..f2a33fb554 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,9 +6,9 @@ ktlint = "1.0.1" junit = "5.10.0" junit-platfrom = "1.10.0" guava = "32.1.3-jre" -commons-cli = "1.5.0" -commons-io = "2.14.0" -detekt = "1.23.1" +commons-cli = "1.6.0" +commons-io = "2.15.0" +detekt = "1.23.2" dokka = "1.9.10" gradle-nexus-publish-plugin = "1.3.0" jacoco = "0.8.8" @@ -20,7 +20,7 @@ plexus = "2.1.0" jbool = "1.24" kotlin-logging = "5.1.0" -log4j2 = "2.21.0" +log4j2 = "2.21.1" kaml = "0.55.0" kotlin-multiplatform-diff = "0.4.0" sarif4k = "0.5.0"