Skip to content

Commit

Permalink
Fixed warning FUNCTION_BOOLEAN_PREFIX on operator fun (#1767)
Browse files Browse the repository at this point in the history
* Fixed warning `FUNCTION_BOOLEAN_PREFIX` on `operator fun`

### What's done:
- fixed warning `FUNCTION_BOOLEAN_PREFIX` on `operator fun`.
- added `hasBooleanReturnType()` and `isOperatorFun()` function checks.
- added warning test.


* Closes #1723
  • Loading branch information
diphtongue authored Nov 1, 2023
1 parent c28f1a1 commit 9423c75
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -403,19 +402,15 @@ class IdentifierNaming(configRules: List<RulesConfig>) : 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)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@file:Suppress(
"LargeClass"
)

package com.saveourtool.diktat.ruleset.chapter1

import com.saveourtool.diktat.common.config.rules.DIKTAT_RULE_SET_ID
Expand Down Expand Up @@ -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<Boolean>()
""".trimIndent()
)
}

@Test
@Tag(WarningNames.IDENTIFIER_LENGTH)
fun `regression - function argument type`() {
Expand Down

0 comments on commit 9423c75

Please sign in to comment.