mirror of
https://github.com/jlengrand/detekt.git
synced 2026-03-10 08:11:23 +00:00
Add DeprecatedBlockTag rule (#3660)
* Add DeprecatedBlockTag rule * Refactor DeprecatedBlockTagSpec tests to remove Spek complexity * Fix incorrect deprecation test snippets on property set/get * Add link to official docs in DeprecatedBlockTag * Extract KDocStyle class out of EndOfSentenceFormat.kt * Fix EndOfSentenceFormat not visiting declarations on its own * Add DeprecatedBlockTag to KDocStyle * Fix code made useless by DeprecatedBlockTag move
This commit is contained in:
@@ -57,6 +57,8 @@ comments:
|
||||
active: false
|
||||
CommentOverPrivateProperty:
|
||||
active: false
|
||||
DeprecatedBlockTag:
|
||||
active: false
|
||||
EndOfSentenceFormat:
|
||||
active: false
|
||||
endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package io.gitlab.arturbosch.detekt.rules.documentation
|
||||
|
||||
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.psi.KtDeclaration
|
||||
|
||||
/**
|
||||
* This rule reports use of the `@deprecated` block tag in KDoc comments. Deprecation must be specified using a
|
||||
* `@Deprecated` annotation as adding a `@deprecated` block tag in KDoc comments
|
||||
* [has no effect and is not supported](https://kotlinlang.org/docs/kotlin-doc.html#suppress). The `@Deprecated`
|
||||
* annotation constructor has dedicated fields for a message and a type (warning, error, etc.). You can also use the
|
||||
* `@ReplaceWith` annotation to specify how to solve the deprecation automatically via the IDE.
|
||||
*
|
||||
* <noncompliant>
|
||||
* /**
|
||||
* * This function prints a message followed by a new line.
|
||||
* *
|
||||
* * @deprecated Useless, the Kotlin standard library can already do this. Replace with println.
|
||||
* */
|
||||
* fun printThenNewline(what: String) {
|
||||
* // ...
|
||||
* }
|
||||
* </noncompliant>
|
||||
*
|
||||
* <compliant>
|
||||
* /**
|
||||
* * This function prints a message followed by a new line.
|
||||
* */
|
||||
* @Deprecated("Useless, the Kotlin standard library can already do this.")
|
||||
* @ReplaceWith("println(what)")
|
||||
* fun printThenNewline(what: String) {
|
||||
* // ...
|
||||
* }
|
||||
* </compliant>
|
||||
*/
|
||||
class DeprecatedBlockTag(config: Config = Config.empty) : Rule(config) {
|
||||
override val issue = Issue(
|
||||
"DeprecatedBlockTag",
|
||||
Severity.Defect,
|
||||
"Do not use the @deprecated block tag, which is not supported by KDoc. " +
|
||||
"Use the @Deprecated annotation instead.",
|
||||
Debt.FIVE_MINS
|
||||
)
|
||||
|
||||
override fun visitDeclaration(dcl: KtDeclaration) {
|
||||
super.visitDeclaration(dcl)
|
||||
verify(dcl)
|
||||
}
|
||||
|
||||
fun verify(dcl: KtDeclaration) {
|
||||
dcl.docComment?.getAllSections()?.forEach { section ->
|
||||
section.findTagsByName("deprecated").forEach { tag ->
|
||||
report(
|
||||
CodeSmell(
|
||||
issue,
|
||||
Entity.from(dcl),
|
||||
"@deprecated tag block does not properly report deprecation in Kotlin, use @Deprecated " +
|
||||
"annotation instead",
|
||||
references = listOf(Entity.from(tag))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,26 +5,11 @@ 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.MultiRule
|
||||
import io.gitlab.arturbosch.detekt.api.Rule
|
||||
import io.gitlab.arturbosch.detekt.api.Severity
|
||||
import io.gitlab.arturbosch.detekt.rules.lastArgumentMatchesUrl
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
|
||||
class KDocStyle(config: Config = Config.empty) : MultiRule() {
|
||||
|
||||
private val endOfSentenceFormat = EndOfSentenceFormat(config)
|
||||
|
||||
override val rules = listOf(
|
||||
endOfSentenceFormat
|
||||
)
|
||||
|
||||
override fun visitDeclaration(dcl: KtDeclaration) {
|
||||
super.visitDeclaration(dcl)
|
||||
endOfSentenceFormat.verify(dcl)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This rule validates the end of the first sentence of a KDoc comment.
|
||||
* It should end with proper punctuation or with a correct URL.
|
||||
@@ -46,6 +31,11 @@ class EndOfSentenceFormat(config: Config = Config.empty) : Rule(config) {
|
||||
Regex(valueOrDefault(END_OF_SENTENCE_FORMAT, "([.?!][ \\t\\n\\r\\f<])|([.?!:]\$)"))
|
||||
private val htmlTag = Regex("<.+>")
|
||||
|
||||
override fun visitDeclaration(dcl: KtDeclaration) {
|
||||
super.visitDeclaration(dcl)
|
||||
verify(dcl)
|
||||
}
|
||||
|
||||
fun verify(declaration: KtDeclaration) {
|
||||
declaration.docComment?.let {
|
||||
val text = it.getDefaultSection().getContent()
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.gitlab.arturbosch.detekt.rules.documentation
|
||||
|
||||
import io.gitlab.arturbosch.detekt.api.Config
|
||||
import io.gitlab.arturbosch.detekt.api.MultiRule
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
|
||||
class KDocStyle(config: Config = Config.empty) : MultiRule() {
|
||||
|
||||
private val deprecatedBlockTag = DeprecatedBlockTag(config)
|
||||
private val endOfSentenceFormat = EndOfSentenceFormat(config)
|
||||
|
||||
override val rules = listOf(
|
||||
deprecatedBlockTag,
|
||||
endOfSentenceFormat
|
||||
)
|
||||
|
||||
override fun visitDeclaration(dcl: KtDeclaration) {
|
||||
super.visitDeclaration(dcl)
|
||||
deprecatedBlockTag.verify(dcl)
|
||||
endOfSentenceFormat.verify(dcl)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package io.gitlab.arturbosch.detekt.rules.documentation
|
||||
|
||||
import io.gitlab.arturbosch.detekt.test.assertThat
|
||||
import io.gitlab.arturbosch.detekt.test.compileAndLint
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
class DeprecatedBlockTagSpec : Spek({
|
||||
val subject by memoized { DeprecatedBlockTag() }
|
||||
describe("DeprecatedBlockTag rule") {
|
||||
it("does not report regular kdoc block") {
|
||||
val code = """
|
||||
/**
|
||||
* This is just a regular kdoc block.
|
||||
*
|
||||
* Nothing to see here...
|
||||
*/
|
||||
val v = 2
|
||||
"""
|
||||
assertThat(subject.compileAndLint(code)).hasSize(0)
|
||||
}
|
||||
|
||||
describe("reporting deprecation tag on kdoc block") {
|
||||
val code = """
|
||||
/**
|
||||
* I am a KDoc block
|
||||
*
|
||||
* @deprecated oh no, this should not be here
|
||||
*/
|
||||
fun ohNo() { }
|
||||
"""
|
||||
|
||||
it("has found something") {
|
||||
assertThat(subject.compileAndLint(code)).hasSize(1)
|
||||
}
|
||||
|
||||
it("correct message") {
|
||||
assertThat(subject.compileAndLint(code)[0]).hasMessage(
|
||||
"@deprecated tag block does not properly report " +
|
||||
"deprecation in Kotlin, use @Deprecated annotation instead"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
describe("reporting deprecation tag wherever @Deprecated is available") {
|
||||
|
||||
it("report deprecation tag on class") {
|
||||
val code = """
|
||||
/**
|
||||
* Hello there
|
||||
*
|
||||
* @deprecated This thing is deprecated
|
||||
*/
|
||||
class Thing { }
|
||||
"""
|
||||
assertThat(subject.compileAndLint(code)).hasSize(1)
|
||||
}
|
||||
|
||||
it("report deprecation tag on property") {
|
||||
val code = """
|
||||
class Thing {
|
||||
/**
|
||||
* A thing you should not use
|
||||
*
|
||||
* @deprecated Do not use that
|
||||
*/
|
||||
val doNotUseMe = 0
|
||||
}
|
||||
"""
|
||||
assertThat(subject.compileAndLint(code)).hasSize(1)
|
||||
}
|
||||
|
||||
it("report deprecation tag on annotation class") {
|
||||
val code = """
|
||||
/**
|
||||
* An annotation you should not use
|
||||
*
|
||||
* @deprecated Do not use that
|
||||
*/
|
||||
annotation class Thing()
|
||||
"""
|
||||
assertThat(subject.compileAndLint(code)).hasSize(1)
|
||||
}
|
||||
|
||||
it("report deprecation tag on constructor") {
|
||||
val code = """
|
||||
class Thing {
|
||||
/**
|
||||
* A constructor you should not use
|
||||
*
|
||||
* @deprecated Do not use that
|
||||
*/
|
||||
constructor(something: String)
|
||||
}
|
||||
"""
|
||||
assertThat(subject.compileAndLint(code)).hasSize(1)
|
||||
}
|
||||
|
||||
it("report deprecation tag on property setter") {
|
||||
val code = """
|
||||
class Thing {
|
||||
var someProperty: Int
|
||||
get() = 10
|
||||
/**
|
||||
* Do not use this setter
|
||||
*
|
||||
* @deprecated Do not use it
|
||||
*/
|
||||
set(value) { println(value) }
|
||||
}
|
||||
"""
|
||||
assertThat(subject.compileAndLint(code)).hasSize(1)
|
||||
}
|
||||
|
||||
it("report deprecation tag on property getter") {
|
||||
val code = """
|
||||
class Thing {
|
||||
var someProperty: Int
|
||||
/**
|
||||
* Do not use this getter
|
||||
*
|
||||
* @deprecated Do not use it
|
||||
*/
|
||||
get() = 10
|
||||
set(value) { println(value) }
|
||||
}
|
||||
"""
|
||||
assertThat(subject.compileAndLint(code)).hasSize(1)
|
||||
}
|
||||
|
||||
it("report deprecation tag on typealias") {
|
||||
val code = """
|
||||
/**
|
||||
* This alias is pointless, do not use it
|
||||
*
|
||||
* @deprecated Do not use this typealias
|
||||
*/
|
||||
typealias VeryString = String
|
||||
"""
|
||||
assertThat(subject.compileAndLint(code)).hasSize(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -6,7 +6,7 @@ import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
class EndOfSentenceFormatSpec : Spek({
|
||||
val subject by memoized { KDocStyle() }
|
||||
val subject by memoized { EndOfSentenceFormat() }
|
||||
|
||||
describe("KDocStyle rule") {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user