Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rule 6.1.5: Explicit supertype qualification should not be used if there is not clash between called methods #458

Merged
merged 15 commits into from
Nov 16, 2020
4 changes: 4 additions & 0 deletions diktat-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -331,5 +331,9 @@
configuration: {}
# Checks that never use the name of a variable in the custom getter or setter
- name: WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR
enabled: true
configuration: {}
# Checks that override function is useful
kentr0w marked this conversation as resolved.
Show resolved Hide resolved
- name: USELESS_OVERRIDE
enabled: true
configuration: {}
2 changes: 2 additions & 0 deletions diktat-rules/src/main/kotlin/generated/WarningNames.kt
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,6 @@ public object WarningNames {

public const val WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR: String =
"WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR"

public const val USELESS_OVERRIDE: String = "USELESS_OVERRIDE"
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ enum class Warnings(private val canBeAutoCorrected: Boolean, private val warn: S
// ======== chapter 6 ========
USE_DATA_CLASS(false, "this class can be converted to a data class"),
WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR(false, "Use `field` keyword instead of property name inside property accessors"),
USELESS_OVERRIDE(true,"override method doesn't differ from super"),
kentr0w marked this conversation as resolved.
Show resolved Hide resolved
;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class DiktatRuleSetProvider(private val diktatConfigFile: String = "diktat-analy
::FileSize,
::DataClassesRule,
::IdentifierNaming,
::UselessOverride,
::LocalVariablesRule,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you move LocalVariablesRule on purpose?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it was my a mistake during the merge

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, github shows it's still there

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move LocalVariablesRule back if it's unintended move, the rest seems fine.

::ClassLikeStructuresOrderRule,
::BracesInConditionalsAndLoopsRule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.cqfn.diktat.ruleset.rules

import com.pinterest.ktlint.core.Rule
import com.pinterest.ktlint.core.ast.ElementType.BLOCK
import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT
import com.pinterest.ktlint.core.ast.ElementType.DOT_QUALIFIED_EXPRESSION
import com.pinterest.ktlint.core.ast.ElementType.EOL_COMMENT
import com.pinterest.ktlint.core.ast.ElementType.EQ
import com.pinterest.ktlint.core.ast.ElementType.FUN
import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER
import com.pinterest.ktlint.core.ast.ElementType.KDOC
import com.pinterest.ktlint.core.ast.ElementType.LBRACE
import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST
import com.pinterest.ktlint.core.ast.ElementType.OVERRIDE_KEYWORD
import com.pinterest.ktlint.core.ast.ElementType.RBRACE
import com.pinterest.ktlint.core.ast.ElementType.SUPER_EXPRESSION
import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE
import org.cqfn.diktat.common.config.rules.RulesConfig
import org.cqfn.diktat.ruleset.constants.Warnings.USELESS_OVERRIDE
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.psi.psiUtil.siblings

/**
* rule 6.1.5
* Explicit supertype qualification should not be used if there is not clash between called methods
*/
class UselessOverride(private val configRules: List<RulesConfig>) : Rule("useless-override") {

companion object {
private val USELESS_CHILDREN_OVERRIDE_FUNCTION = listOf(WHITE_SPACE, LBRACE,
RBRACE, DOT_QUALIFIED_EXPRESSION, KDOC, EOL_COMMENT, BLOCK_COMMENT)
}

private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit)
private var isFixMode: Boolean = false

override fun visit(node: ASTNode,
autoCorrect: Boolean,
emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) {
emitWarn = emit
isFixMode = autoCorrect

if(node.elementType == FUN)
checkFun(node)
}

@Suppress("UnsafeCallOnNullableType")
private fun checkFun(node: ASTNode) {
if (node.getChildren(TokenSet.create(MODIFIER_LIST)).any { it.elementType == OVERRIDE_KEYWORD })
return
val functionBody = (node.findChildByType(BLOCK)?.getChildren(null)?.toList() ?: node.findChildByType(EQ)!!.siblings(true).toList())
if (USELESS_CHILDREN_OVERRIDE_FUNCTION.containsAll(functionBody.map { it.elementType })) {
if (functionBody.find { it.elementType == DOT_QUALIFIED_EXPRESSION }?.findChildByType(SUPER_EXPRESSION) != null) {
USELESS_OVERRIDE.warnAndFix(configRules, emitWarn, isFixMode, node.findChildByType(IDENTIFIER)!!.text, node.startOffset, node) {
val parentNode = node.treeParent
if (node.treeNext != null && node.treeNext.elementType == WHITE_SPACE)
parentNode.removeChild(node.treeNext)
parentNode.removeChild(node)
}
}
}
}
}
4 changes: 4 additions & 0 deletions diktat-rules/src/main/resources/diktat-analysis-huawei.yml
Original file line number Diff line number Diff line change
Expand Up @@ -330,5 +330,9 @@
configuration: {}
# Checks that never use the name of a variable in the custom getter or setter
- name: WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR
enabled: true
configuration: {}
# Checks that override function is useful
- name: USELESS_OVERRIDE
enabled: true
configuration: {}
4 changes: 4 additions & 0 deletions diktat-rules/src/main/resources/diktat-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -332,5 +332,9 @@
configuration: {}
# Checks that never use the name of a variable in the custom getter or setter
- name: WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR
enabled: true
configuration: {}
# Checks that override function is useful
- name: USELESS_OVERRIDE
enabled: true
configuration: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.cqfn.diktat.ruleset.chapter6

import generated.WarningNames
import org.cqfn.diktat.util.FixTestBase
import org.cqfn.diktat.ruleset.rules.UselessOverride
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test

class UselessOverrideFixTest : FixTestBase("test/paragraph6/useless-override", ::UselessOverride) {

@Test
@Tag(WarningNames.USELESS_OVERRIDE)
fun `fix nested functions`() {
fixAndCompare("UselessOverrideExpected.kt", "UselessOverrideTest.kt")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.cqfn.diktat.ruleset.chapter6

import com.pinterest.ktlint.core.LintError
import generated.WarningNames
import org.cqfn.diktat.ruleset.constants.Warnings.USELESS_OVERRIDE
import org.cqfn.diktat.ruleset.rules.DIKTAT_RULE_SET_ID
import org.cqfn.diktat.ruleset.rules.UselessOverride
import org.cqfn.diktat.util.LintTestBase
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.Test

class UselessOverrideWarnTest: LintTestBase(::UselessOverride) {

private val ruleId = "$DIKTAT_RULE_SET_ID:useless-override"

@Test
@Tag(WarningNames.USELESS_OVERRIDE)
fun `check simple wrong examples`() {
lintMethod(
"""
open class Rectangle {
open fun draw() { /* ... */ }
}

class Square() : Rectangle() {
override fun draw() {
/**
*
* hehe
*/
super<Rectangle>.draw()
}
}

class Square2() : Rectangle() {
override fun draw() {
//hehe
/*
hehe
*/
super<Rectangle>.draw()
}
}

class Square2() : Rectangle() {
override fun draw() {
val q = super.draw()
}
}

class A: Runnable {
override fun run() {

}
}
""".trimMargin(),
LintError(6,25, ruleId, "${USELESS_OVERRIDE.warnText()} draw", true),
LintError(16,25, ruleId, "${USELESS_OVERRIDE.warnText()} draw", true)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package test.paragraph6

open class Rectangle {
open fun draw() { /* ... */ }
}

class Square() : Rectangle() {
}

class Square2() : Rectangle() {
}

class Square2() : Rectangle() {
override fun draw() {
val q = super.draw()
}
}

class A: Runnable {
override fun run() {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package test.paragraph6

open class Rectangle {
open fun draw() { /* ... */ }
}

class Square() : Rectangle() {
override fun draw() {
/**
*
* hehe
*/
super<Rectangle>.draw()
}
}

class Square2() : Rectangle() {
override fun draw() {
//hehe
/*
hehe
*/
super<Rectangle>.draw()
}
}

class Square2() : Rectangle() {
override fun draw() {
val q = super.draw()
}
}

class A: Runnable {
override fun run() {

}
}
3 changes: 2 additions & 1 deletion info/available-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,6 @@
| 5 | 5.2.1 | LAMBDA_IS_NOT_LAST_PARAMETER | Checks that lambda inside function parameters isn't in the end | no | - |
| 5 | 5.2.2 | TOO_MANY_PARAMETERS | Check: if function contains more parameters than allowed | no | maxParameterListSize |
| 5 | 5.2.3 | WRONG_OVERLOADING_FUNCTION_ARGUMENTS | Check: function has overloading instead use default arguments | no | -|
| 6 | 6.1.2 | USE_DATA_CLASS | Check: if class can be made as data class | no | - | yes |
| 6 | 6.1.2 | USE_DATA_CLASS | Check: if class can be made as data class | no | - | yes |\
| 6 | 6.1.5 | USELESS_OVERRIDE | Check: if override function can be removed | yes| - | |
| 6 | 6.1.9 | WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR | Check: used the name of a variable in the custom getter or setter | no | - |