From baac14ca4faceb4eac6f68029c5294c288d3e9bc Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Tue, 12 Nov 2019 00:52:25 +0300 Subject: [PATCH] Suppress remove curly braces from template #157 (#263) Adds a way to respect standard suppress code style annotations. --- .../com/pinterest/ktlint/core/KtLint.kt | 48 +++++++++++++++++++ .../spec/string-template/lint.kt.spec | 32 ++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/KtLint.kt b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/KtLint.kt index d711633bbe..98a408a0fd 100644 --- a/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/KtLint.kt +++ b/ktlint-core/src/main/kotlin/com/pinterest/ktlint/core/KtLint.kt @@ -35,7 +35,11 @@ import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.TreeCopyHandler import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.psi.KtAnnotated +import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.startOffset import sun.reflect.ReflectionFactory object KtLint { @@ -466,6 +470,14 @@ object KtLint { } } } + // Extract all Suppress annotations and create SuppressionHints + val psi = node.psi + if (psi is KtAnnotated) { + createSuppressionHintFromAnnotations(psi, suppressAnnotations, suppressAnnotationRuleMap) + ?.let { + result.add(it) + } + } } result.addAll( open.map { @@ -490,6 +502,42 @@ object KtLint { comment.replace(Regex("\\s"), " ").replace(" {2,}", " ").split(" ") private fun List.tail() = this.subList(1, this.size) + + private val suppressAnnotationRuleMap = mapOf( + "RemoveCurlyBracesFromTemplate" to "string-template" + ) + + private val suppressAnnotations = setOf("Suppress", "SuppressWarnings") + + /** + * Creates [SuppressionHint] from annotations of given [psi] + * Returns null if no [targetAnnotations] present or no mapping exists + * between annotations' values and ktlint rules + */ + private fun createSuppressionHintFromAnnotations( + psi: KtAnnotated, + targetAnnotations: Collection, + annotationValueToRuleMapping: Map + ): SuppressionHint? { + + return psi.annotationEntries + .filter { + it.calleeExpression?.constructorReferenceExpression + ?.getReferencedName() in targetAnnotations + }.flatMap(KtAnnotationEntry::getValueArguments) + .mapNotNull { it.getArgumentExpression()?.text?.removeSurrounding("\"") } + .mapNotNull(annotationValueToRuleMapping::get) + .let { suppressedRules -> + if (suppressedRules.isNotEmpty()) { + SuppressionHint( + IntRange(psi.startOffset, psi.endOffset), + suppressedRules.toSet() + ) + } else { + null + } + } + } } } diff --git a/ktlint-ruleset-standard/src/test/resources/spec/string-template/lint.kt.spec b/ktlint-ruleset-standard/src/test/resources/spec/string-template/lint.kt.spec index 20e09901fb..0ac10e805c 100644 --- a/ktlint-ruleset-standard/src/test/resources/spec/string-template/lint.kt.spec +++ b/ktlint-ruleset-standard/src/test/resources/spec/string-template/lint.kt.spec @@ -15,10 +15,39 @@ fun main() { println("${h["x-forwarded-proto"] ?: "http"}") println("${if (diff > 0) "expanded" else if (diff < 0) "shrank" else "changed"}") + + @Suppress("RemoveCurlyBracesFromTemplate") + println("${s0}") + @Suppress("RemoveCurlyBracesFromTemplate", "Unused") + println("${s0}") + @Suppress("RemoveCurlyBracesFromTemplate") + val t = "${s0}" } class B(val k: String) { override fun toString(): String = "${super.toString()}, ${super.hashCode().toString()}, k=$k" + + @Suppress("RemoveCurlyBracesFromTemplate") + val a + get() = "${s0}" +} + +@Suppress("RemoveCurlyBracesFromTemplate") +class C { + override fun toString(): String = "${s0}" +} + +// Ensure that suppression scope is as wide as it should be +class D { + @Suppress("RemoveCurlyBracesFromTemplate") + override fun toString(): String = "${s0}" + + fun test() = "${s0}" +} + +@SuppressWarnings("RemoveCurlyBracesFromTemplate") +class E { + override fun toString(): String = "${s0}" } // expect @@ -26,4 +55,5 @@ class B(val k: String) { // 3:28:Redundant "toString()" call in string template // 6:15:Redundant curly braces // 7:15:Redundant curly braces -// 21:79:Redundant "toString()" call in string template +// 28:79:Redundant "toString()" call in string template +// 45:20:Redundant curly braces