Allow to suppress kotlin inspections with Suppress() annotation
This commit is contained in:
committed by
Nikolay Krasko
parent
ef265e23f8
commit
36210f0a27
+26
-2
@@ -20,36 +20,44 @@ import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import com.intellij.util.containers.SLRUCache
|
||||
import org.jetbrains.kotlin.analyzer.EmptyResolverForProject
|
||||
import org.jetbrains.kotlin.container.getService
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider
|
||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.psi.KtAnnotated
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
|
||||
internal val LOG = Logger.getInstance(javaClass<KotlinCacheService>())
|
||||
internal val LOG = Logger.getInstance(KotlinCacheService::class.java)
|
||||
|
||||
public class KotlinCacheService(val project: Project) {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
public fun getInstance(project: Project): KotlinCacheService = ServiceManager.getService(project, javaClass<KotlinCacheService>())!!
|
||||
public fun getInstance(project: Project): KotlinCacheService = ServiceManager.getService(project, KotlinCacheService::class.java)!!
|
||||
}
|
||||
|
||||
public fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade {
|
||||
return getFacadeToAnalyzeFiles(elements.map { it.getContainingKtFile() })
|
||||
}
|
||||
|
||||
public fun getSuppressionCache(): KotlinSuppressCache = kotlinSuppressCache.value
|
||||
|
||||
private val globalFacadesPerPlatform = listOf(JvmPlatform, JsPlatform).keysToMap { platform -> GlobalFacade(platform) }
|
||||
|
||||
private inner class GlobalFacade(platform: TargetPlatform) {
|
||||
@@ -147,6 +155,22 @@ public class KotlinCacheService(val project: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
private val kotlinSuppressCache: CachedValue<KotlinSuppressCache> = CachedValuesManager.getManager(project).createCachedValue({
|
||||
CachedValueProvider.Result<KotlinSuppressCache>(object : KotlinSuppressCache() {
|
||||
override fun getSuppressionAnnotations(annotated: KtAnnotated): List<AnnotationDescriptor> {
|
||||
val context = annotated.analyze(BodyResolveMode.PARTIAL)
|
||||
val annotatedDescriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, annotated)
|
||||
|
||||
if (annotatedDescriptor != null) {
|
||||
return annotatedDescriptor.annotations.toList()
|
||||
}
|
||||
else {
|
||||
return annotated.annotationEntries.map { context.get(BindingContext.ANNOTATION, it) }.filterNotNull()
|
||||
}
|
||||
}
|
||||
}, LibraryModificationTracker.getInstance(project), PsiModificationTracker.MODIFICATION_COUNT)
|
||||
}, false)
|
||||
|
||||
private val syntheticFileCachesLock = Any()
|
||||
|
||||
private val slruCacheProvider = CachedValueProvider {
|
||||
|
||||
+31
-4
@@ -16,12 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionTool
|
||||
import com.intellij.codeInspection.CustomSuppressableInspectionTool
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey
|
||||
import com.intellij.codeInspection.CustomSuppressableInspectionTool
|
||||
import com.intellij.codeInspection.LocalInspectionTool
|
||||
import com.intellij.codeInspection.SuppressIntentionAction
|
||||
import com.intellij.codeInspection.SuppressManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService
|
||||
|
||||
public abstract class AbstractKotlinInspection: LocalInspectionTool(), CustomSuppressableInspectionTool {
|
||||
public override fun getSuppressActions(element: PsiElement?): Array<SuppressIntentionAction>? {
|
||||
@@ -29,6 +32,30 @@ public abstract class AbstractKotlinInspection: LocalInspectionTool(), CustomSup
|
||||
}
|
||||
|
||||
public override fun isSuppressedFor(element: PsiElement): Boolean {
|
||||
return SuppressManager.getInstance()!!.isSuppressedFor(element, getID())
|
||||
if (SuppressManager.getInstance()!!.isSuppressedFor(element, getID())) {
|
||||
return true
|
||||
}
|
||||
|
||||
val project = element.project
|
||||
if (KotlinCacheService.getInstance(project).getSuppressionCache().isSuppressed(element, this.shortName, toSeverity(defaultLevel))) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public fun toSeverity(highlightDisplayLevel: HighlightDisplayLevel): Severity {
|
||||
return when (highlightDisplayLevel) {
|
||||
HighlightDisplayLevel.DO_NOT_SHOW -> Severity.INFO
|
||||
|
||||
HighlightDisplayLevel.WARNING,
|
||||
HighlightDisplayLevel.WEAK_WARNING -> Severity.WARNING
|
||||
|
||||
HighlightDisplayLevel.ERROR,
|
||||
HighlightDisplayLevel.GENERIC_SERVER_ERROR_OR_WARNING,
|
||||
HighlightDisplayLevel.NON_SWITCHABLE_ERROR -> Severity.ERROR
|
||||
|
||||
else -> Severity.ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -91,7 +91,9 @@ public abstract class SelfTargetingIntention<TElement : KtElement>(
|
||||
val inspection = findInspection(javaClass) ?: return false
|
||||
|
||||
val key = HighlightDisplayKey.find(inspection.shortName)
|
||||
if (!InspectionProjectProfileManager.getInstance(project).getInspectionProfile(target).isToolEnabled(key)) return false
|
||||
if (!InspectionProjectProfileManager.getInstance(project).getInspectionProfile(target).isToolEnabled(key)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return inspection.intentions.single { it.intention.javaClass == javaClass }.additionalChecker(target)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
class Klass {
|
||||
fun unused() {
|
||||
fun unusedFun() {
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun unusedNoWarn() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
class OtherKlass {
|
||||
fun unusedNoWarn() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Klass()
|
||||
OtherKlass()
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
|
||||
<problem>
|
||||
<file>topLevelOnlyInImport.kt</file>
|
||||
<line>5</line>
|
||||
<line>6</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/topLevelOnlyInImport.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||
|
||||
@@ -2,4 +2,16 @@ fun outer() {
|
||||
fun local() {
|
||||
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun localNoWarn() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun otherFun() {
|
||||
fun localNoWarn() {
|
||||
|
||||
}
|
||||
}
|
||||
+16
-1
@@ -3,6 +3,9 @@ class Klass {
|
||||
fun f() {
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun fNoWarn() {}
|
||||
|
||||
val p = 5
|
||||
}
|
||||
|
||||
@@ -16,9 +19,21 @@ class Klass {
|
||||
fun f() {
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun fNoWarn() {}
|
||||
|
||||
val p = 5
|
||||
}
|
||||
|
||||
fun localObject3() = @Suppress("UnusedSymbol") object {
|
||||
fun fNoWarn() {}
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
private val localObject4 = object {
|
||||
fun fNoWarn() {}
|
||||
}
|
||||
|
||||
init {
|
||||
localObject2().f()
|
||||
localObject2().p
|
||||
@@ -39,5 +54,5 @@ class Klass {
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Klass()
|
||||
Klass().localObject3()
|
||||
}
|
||||
+8
@@ -14,9 +14,17 @@ fun main(args: Array<String>) {
|
||||
fun f() {
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun fNoWarn() {}
|
||||
|
||||
val p = 5
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun localObject3() = object {
|
||||
fun fNoWarn() {}
|
||||
}
|
||||
|
||||
localObject2().f()
|
||||
localObject2().p
|
||||
|
||||
|
||||
@@ -3,10 +3,25 @@ fun main(args: Array<String>) {
|
||||
fun f() {
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun fNoWarn() {}
|
||||
|
||||
val p = 5
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
class OtherClass {
|
||||
fun fNoWarn() {}
|
||||
}
|
||||
|
||||
|
||||
LocalClass().f()
|
||||
LocalClass().p
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun other() {
|
||||
class OtherClass {
|
||||
fun fNoWarn() {}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
package foo
|
||||
|
||||
import foo.onlyInImport
|
||||
import foo.onlyInImportNoWarn
|
||||
|
||||
fun onlyInImport() {
|
||||
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun onlyInImportNoWarn() {}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
fun unused() {
|
||||
fun unusedFun() {
|
||||
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun unusedNoWarn() {}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
fun usedOnlyRecursively() {
|
||||
usedOnlyRecursively()
|
||||
}
|
||||
|
||||
@Suppress("UnusedSymbol")
|
||||
fun usedOnlyRecursivelyNoWarn() {
|
||||
usedOnlyRecursivelyNoWarn()
|
||||
}
|
||||
+11
@@ -7,3 +7,14 @@ fun test() {
|
||||
i
|
||||
}
|
||||
}
|
||||
|
||||
fun withSuppression() {
|
||||
class Test{
|
||||
operator fun get(a: Int, b: Int, fn: (i: Int) -> Int) : Int = 0
|
||||
}
|
||||
|
||||
val test = Test()
|
||||
|
||||
@Suppress("ReplaceGetOrSet")
|
||||
test.get(1, 2) { i -> i }
|
||||
}
|
||||
|
||||
+11
@@ -7,3 +7,14 @@ fun test() {
|
||||
i
|
||||
}]
|
||||
}
|
||||
|
||||
fun withSuppression() {
|
||||
class Test{
|
||||
operator fun get(a: Int, b: Int, fn: (i: Int) -> Int) : Int = 0
|
||||
}
|
||||
|
||||
val test = Test()
|
||||
|
||||
@Suppress("ReplaceGetOrSet")
|
||||
test.get(1, 2) { i -> i }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user