Skip to content

Commit

Permalink
Support suppressing of different rules - #6
Browse files Browse the repository at this point in the history
  • Loading branch information
arturbosch committed May 4, 2017
1 parent 8cb34a8 commit f0356c9
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getTextWithLocation
import org.jetbrains.kotlin.psi.psiUtil.startOffset
Expand Down Expand Up @@ -172,15 +173,15 @@ data class Location(val source: SourceLocation,
return Location(sourceLocation, textLocation, locationText, fileName)
}

private fun PsiElement.originalFilePath(): String? {
return (this.containingFile.viewProvider.virtualFile as LightVirtualFile).originalFile?.name
}

private fun startLineAndColumn(element: PsiElement, offset: Int): DiagnosticUtils.LineAndColumn {
fun startLineAndColumn(element: PsiElement, offset: Int = 0): DiagnosticUtils.LineAndColumn {
val range = element.textRange
return DiagnosticUtils.getLineAndColumnInPsiFile(element.containingFile,
TextRange(range.startOffset + offset, range.endOffset + offset))
}

private fun PsiElement.originalFilePath(): String? {
return (this.containingFile.viewProvider.virtualFile as LightVirtualFile).originalFile?.name
}
}
}

Expand All @@ -190,7 +191,8 @@ data class Location(val source: SourceLocation,
data class Entity(val name: String,
val className: String,
val signature: String,
val location: Location) : Compactable {
val location: Location,
val ktElement: KtElement? = null) : Compactable {

override fun compact(): String {
return "[$name] - ${location.compact()}"
Expand All @@ -201,7 +203,8 @@ data class Entity(val name: String,
val name = element.searchName()
val signature = element.buildFullSignature()
val clazz = element.searchClass()
return Entity(name, clazz, signature, Location.from(element, offset))
return Entity(name, clazz, signature, Location.from(element, offset),
if (element is KtElement) element else null)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.gitlab.arturbosch.detekt.api

import org.jetbrains.kotlin.preprocessor.typeReferenceName
import org.jetbrains.kotlin.psi.KtFile

/**
Expand Down Expand Up @@ -52,20 +51,14 @@ abstract class Rule(val id: String,
*/
open fun visit(root: KtFile) {
ifRuleActive {
if (!root.isSuppressed()) {
if (!root.isSuppressedBy(id)) {
preVisit(root)
root.accept(this)
postVisit(root)
}
}
}

private fun KtFile.isSuppressed(): Boolean {
return annotationEntries.find { it.typeReferenceName == "SuppressWarnings" }
?.valueArguments
?.find { it.getArgumentExpression()?.text?.replace("\"", "") == id } != null
}

/**
* If custom configurable attributes are provided, use this method to retrieve
* properties from the sub configuration specified by the rule id.
Expand Down Expand Up @@ -112,8 +105,14 @@ abstract class Rule(val id: String,

/**
* The only way to add code smell findings.
*
* Before adding a finding, it is checked if it is not suppressed
* by @Suppress or @SuppressWarnings annotations.
*/
protected fun addFindings(vararg finding: Finding) {
_findings.addAll(finding)
_findings.addAll(finding.filter {
val ktElement = it.entity.ktElement
ktElement == null || !ktElement.isSuppressedBy(id)
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.gitlab.arturbosch.detekt.api

import org.jetbrains.kotlin.preprocessor.typeReferenceName
import org.jetbrains.kotlin.psi.KtAnnotated
import org.jetbrains.kotlin.psi.KtElement

/**
* @author Artur Bosch
*/

/**
* Checks if this psi element is suppressed by @Suppress or @SuppressWarnings annotations.
*/
fun KtElement.isSuppressedBy(id: String): Boolean {
return this is KtAnnotated && this.isSuppressedBy(id)
}

/**
* Checks if this kt element is suppressed by @Suppress or @SuppressWarnings annotations.
*/
fun KtAnnotated.isSuppressedBy(id: String): Boolean {
return annotationEntries.find { it.typeReferenceName == "SuppressWarnings" }
?.valueArguments
?.find { it.getArgumentExpression()?.text?.replace("\"", "") == id } != null
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.it
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

/**
Expand All @@ -25,6 +28,13 @@ internal class RuleTest : Spek({
assertNotNull(rule.expected)
}

it("findings are suppressed") {
val ktFile = compilerFor("SuppressedElements.kt")
val ruleSet = RuleSet("Test", listOf(TestLM(), TestLPL()))
val findings = ruleSet.accept(ktFile)
assertEquals(0, findings.size)
}

})

fun compilerFor(resource: String) = Compiler.compileFromContent(
Expand All @@ -51,3 +61,19 @@ class TestRule : Rule("Test") {
expected = null
}
}

class TestLM : Rule("LongMethod") {
override fun visitNamedFunction(function: KtNamedFunction) {
val start = Location.startLineAndColumn(function.funKeyword!!).line
val end = Location.startLineAndColumn(function.lastBlockStatementOrThis()).line
val offset = end - start
if (offset > 10) addFindings(CodeSmell(id, Entity.from(function)))
}
}

class TestLPL : Rule("LongParameterList") {
override fun visitNamedFunction(function: KtNamedFunction) {
val size = function.valueParameters.size
if (size > 5) addFindings(CodeSmell(id, Entity.from(function)))
}
}
34 changes: 34 additions & 0 deletions detekt-api/src/test/resources/SuppressedElements.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @author Artur Bosch
*/

@SuppressWarnings("LongParameterList")
fun lpl(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) = (a + b + c + d + e + f).apply {
assert(false) { "FAILED TEST" }
}

@SuppressWarnings("LongMethod")
fun lm() {
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
lpl(1, 2, 3, 4, 5, 6)
assert(false) { "FAILED TEST" }
}
4 changes: 2 additions & 2 deletions detekt-api/src/test/resources/SuppressedObject.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
object SuppressedObject {

fun stuff() {
println("Stuff")
println("FAILED TEST")
}
}
}

0 comments on commit f0356c9

Please sign in to comment.