Fix inspections and slightly "kotlinify" KotlinSuppressCache

This commit is contained in:
Alexander Udalov
2020-11-02 18:48:47 +01:00
committed by Alexander Udalov
parent 9d3c9a823d
commit 61548a0a36
@@ -39,7 +39,7 @@ interface DiagnosticSuppressor {
companion object { companion object {
val EP_NAME: ExtensionPointName<DiagnosticSuppressor> = val EP_NAME: ExtensionPointName<DiagnosticSuppressor> =
ExtensionPointName.create<DiagnosticSuppressor>("org.jetbrains.kotlin.diagnosticSuppressor") ExtensionPointName.create("org.jetbrains.kotlin.diagnosticSuppressor")
} }
} }
@@ -49,13 +49,13 @@ abstract class KotlinSuppressCache {
// The cache is weak: we're OK with losing it // The cache is weak: we're OK with losing it
private val suppressors = ContainerUtil.createConcurrentWeakValueMap<KtAnnotated, Suppressor>() private val suppressors = ContainerUtil.createConcurrentWeakValueMap<KtAnnotated, Suppressor>()
val filter: (Diagnostic) -> Boolean = { diagnostic: Diagnostic -> !isSuppressed(diagnostic) } val filter: (Diagnostic) -> Boolean = { diagnostic: Diagnostic ->
!isSuppressed(DiagnosticSuppressRequest(diagnostic))
}
fun isSuppressed(psiElement: PsiElement, suppressionKey: String, severity: Severity) = fun isSuppressed(psiElement: PsiElement, suppressionKey: String, severity: Severity) =
isSuppressed(StringSuppressRequest(psiElement, severity, suppressionKey.toLowerCase())) isSuppressed(StringSuppressRequest(psiElement, severity, suppressionKey.toLowerCase()))
fun isSuppressed(diagnostic: Diagnostic): Boolean = isSuppressed(DiagnosticSuppressRequest(diagnostic))
private fun isSuppressed(request: SuppressRequest): Boolean { private fun isSuppressed(request: SuppressRequest): Boolean {
// If diagnostics are reported in a synthetic file generated by KtPsiFactory (dummy.kt), // If diagnostics are reported in a synthetic file generated by KtPsiFactory (dummy.kt),
// there's no point to present such diagnostics to the user, because the user didn't write this code // there's no point to present such diagnostics to the user, because the user didn't write this code
@@ -78,7 +78,7 @@ abstract class KotlinSuppressCache {
return isSuppressedByAnnotated(request.suppressKey, request.severity, annotated, 0) return isSuppressedByAnnotated(request.suppressKey, request.severity, annotated, 0)
} }
open fun isSuppressedByExtension(suppressor: DiagnosticSuppressor, diagnostic: Diagnostic): Boolean { protected open fun isSuppressedByExtension(suppressor: DiagnosticSuppressor, diagnostic: Diagnostic): Boolean {
return suppressor.isSuppressed(diagnostic) return suppressor.isSuppressed(diagnostic)
} }
@@ -111,34 +111,30 @@ abstract class KotlinSuppressCache {
This way we need no more lookups than the number of suppress() annotations from here to the root. This way we need no more lookups than the number of suppress() annotations from here to the root.
*/ */
protected fun isSuppressedByAnnotated(suppressionKey: String, severity: Severity, annotated: KtAnnotated, debugDepth: Int): Boolean { private fun isSuppressedByAnnotated(suppressionKey: String, severity: Severity, annotated: KtAnnotated, debugDepth: Int): Boolean {
val suppressor = getOrCreateSuppressor(annotated) val suppressor = getOrCreateSuppressor(annotated)
if (suppressor.isSuppressed(suppressionKey, severity)) return true if (suppressor.isSuppressed(suppressionKey, severity)) return true
val annotatedAbove = KtStubbedPsiUtil.getPsiOrStubParent(suppressor.annotatedElement, KtAnnotated::class.java, true) ?: return false val annotatedAbove = KtStubbedPsiUtil.getPsiOrStubParent(annotated, KtAnnotated::class.java, true) ?: return false
val suppressed = isSuppressedByAnnotated(suppressionKey, severity, annotatedAbove, debugDepth + 1) val suppressed = isSuppressedByAnnotated(suppressionKey, severity, annotatedAbove, debugDepth + 1)
val suppressorAbove = suppressors[annotatedAbove] val suppressorAbove = suppressors[annotatedAbove]
if (suppressorAbove != null && suppressorAbove.dominates(suppressor)) { if (suppressorAbove != null && suppressorAbove.dominates(suppressor)) {
suppressors.put(annotated, suppressorAbove) suppressors[annotated] = suppressorAbove
} }
return suppressed return suppressed
} }
private fun getOrCreateSuppressor(annotated: KtAnnotated): Suppressor { private fun getOrCreateSuppressor(annotated: KtAnnotated): Suppressor =
var suppressor: Suppressor? = suppressors[annotated] suppressors.getOrPut(annotated) {
if (suppressor == null) {
val strings = getSuppressingStrings(annotated) val strings = getSuppressingStrings(annotated)
suppressor = when { when (strings.size) {
strings.isEmpty() -> EmptySuppressor(annotated) 0 -> EmptySuppressor
strings.size == 1 -> SingularSuppressor(annotated, strings.iterator().next()) 1 -> SingularSuppressor(strings.first())
else -> MultiSuppressor(annotated, strings) else -> MultiSuppressor(strings)
} }
suppressors.put(annotated, suppressor)
} }
return suppressor
}
abstract fun getSuppressionAnnotations(annotated: KtAnnotated): List<AnnotationDescriptor> abstract fun getSuppressionAnnotations(annotated: KtAnnotated): List<AnnotationDescriptor>
@@ -156,7 +152,7 @@ abstract class KotlinSuppressCache {
// We only add strings and skip other values to facilitate recovery in presence of erroneous code // We only add strings and skip other values to facilitate recovery in presence of erroneous code
for (arrayValue in annotationDescriptor.allValueArguments.values) { for (arrayValue in annotationDescriptor.allValueArguments.values) {
if ((arrayValue is ArrayValue)) { if (arrayValue is ArrayValue) {
for (value in arrayValue.value) { for (value in arrayValue.value) {
if (value is StringValue) { if (value is StringValue) {
builder.add(value.value.toLowerCase()) builder.add(value.value.toLowerCase())
@@ -167,36 +163,30 @@ abstract class KotlinSuppressCache {
} }
companion object { companion object {
fun getDiagnosticSuppressKey(diagnostic: Diagnostic): String { private fun getDiagnosticSuppressKey(diagnostic: Diagnostic): String =
return diagnostic.factory.name.toLowerCase() diagnostic.factory.name.toLowerCase()
}
fun isSuppressedByStrings(key: String, strings: Set<String>, severity: Severity): Boolean { private fun isSuppressedByStrings(key: String, strings: Set<String>, severity: Severity): Boolean =
if (strings.contains("warnings") && severity == Severity.WARNING) return true severity == Severity.WARNING && "warnings" in strings || key in strings
return strings.contains(key)
}
} }
private abstract class Suppressor protected constructor(val annotatedElement: KtAnnotated) { private abstract class Suppressor {
abstract fun isSuppressed(diagnostic: Diagnostic): Boolean open fun isSuppressed(diagnostic: Diagnostic): Boolean =
isSuppressed(getDiagnosticSuppressKey(diagnostic), diagnostic.severity)
abstract fun isSuppressed(suppressionKey: String, severity: Severity): Boolean abstract fun isSuppressed(suppressionKey: String, severity: Severity): Boolean
// true is \forall x. other.isSuppressed(x) -> this.isSuppressed(x) // true is \forall x. other.isSuppressed(x) -> this.isSuppressed(x)
abstract fun dominates(other: Suppressor): Boolean abstract fun dominates(other: Suppressor): Boolean
} }
private class EmptySuppressor(annotated: KtAnnotated) : Suppressor(annotated) { private object EmptySuppressor : Suppressor() {
override fun isSuppressed(diagnostic: Diagnostic): Boolean = false override fun isSuppressed(diagnostic: Diagnostic): Boolean = false
override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean = false override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean = false
override fun dominates(other: Suppressor): Boolean = other is EmptySuppressor override fun dominates(other: Suppressor): Boolean = this === other
} }
private class SingularSuppressor(annotated: KtAnnotated, private val string: String) : Suppressor(annotated) { private class SingularSuppressor(private val string: String) : Suppressor() {
override fun isSuppressed(diagnostic: Diagnostic): Boolean {
return isSuppressed(getDiagnosticSuppressKey(diagnostic), diagnostic.severity)
}
override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean { override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean {
return isSuppressedByStrings(suppressionKey, ImmutableSet.of(string), severity) return isSuppressedByStrings(suppressionKey, ImmutableSet.of(string), severity)
} }
@@ -206,11 +196,7 @@ abstract class KotlinSuppressCache {
} }
} }
private class MultiSuppressor(annotated: KtAnnotated, private val strings: Set<String>) : Suppressor(annotated) { private class MultiSuppressor(private val strings: Set<String>) : Suppressor() {
override fun isSuppressed(diagnostic: Diagnostic): Boolean {
return isSuppressed(getDiagnosticSuppressKey(diagnostic), diagnostic.severity)
}
override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean { override fun isSuppressed(suppressionKey: String, severity: Severity): Boolean {
return isSuppressedByStrings(suppressionKey, strings, severity) return isSuppressedByStrings(suppressionKey, strings, severity)
} }
@@ -244,11 +230,8 @@ class BindingContextSuppressCache(val context: BindingContext) : KotlinSuppressC
override fun getSuppressionAnnotations(annotated: KtAnnotated): List<AnnotationDescriptor> { override fun getSuppressionAnnotations(annotated: KtAnnotated): List<AnnotationDescriptor> {
val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, annotated) val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, annotated)
return if (descriptor != null) { return descriptor?.annotations?.toList()
descriptor.annotations.toList() ?: annotated.annotationEntries.mapNotNull { context.get(BindingContext.ANNOTATION, it) }
} else {
annotated.annotationEntries.mapNotNull { context.get(BindingContext.ANNOTATION, it) }
}
} }
override fun isSuppressedByExtension(suppressor: DiagnosticSuppressor, diagnostic: Diagnostic): Boolean { override fun isSuppressedByExtension(suppressor: DiagnosticSuppressor, diagnostic: Diagnostic): Boolean {