org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.diagnostics
import com.google.common.collect.ImmutableSet
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.diagnostics.AbstractKotlinSuppressCache
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.psi.KtAnnotated
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.util.ExtensionProvider
interface DiagnosticSuppressor {
fun isSuppressed(diagnostic: Diagnostic): Boolean
fun isSuppressed(diagnostic: Diagnostic, bindingContext: BindingContext?): Boolean = isSuppressed(diagnostic)
companion object {
val EP_NAME: ExtensionPointName =
ExtensionPointName.create("org.jetbrains.kotlin.diagnosticSuppressor")
}
}
abstract class KotlinSuppressCache : AbstractKotlinSuppressCache() {
private val diagnosticSuppressors = ExtensionProvider.create(DiagnosticSuppressor.EP_NAME)
val filter: (Diagnostic) -> Boolean = { diagnostic: Diagnostic ->
!isSuppressed(DiagnosticSuppressRequest(diagnostic))
}
protected open fun isSuppressedByExtension(suppressor: DiagnosticSuppressor, diagnostic: Diagnostic): Boolean {
return suppressor.isSuppressed(diagnostic)
}
abstract fun getSuppressionAnnotations(annotated: PsiElement): List
override fun getSuppressingStrings(annotated: PsiElement): Set {
val builder = ImmutableSet.builder()
for (annotationDescriptor in getSuppressionAnnotations(annotated)) {
processAnnotation(builder, annotationDescriptor)
}
return builder.build()
}
private fun processAnnotation(builder: ImmutableSet.Builder, annotationDescriptor: AnnotationDescriptor) {
if (annotationDescriptor.fqName != StandardNames.FqNames.suppress) return
// We only add strings and skip other values to facilitate recovery in presence of erroneous code
for (arrayValue in annotationDescriptor.allValueArguments.values) {
if (arrayValue is ArrayValue) {
for (value in arrayValue.value) {
if (value is StringValue) {
builder.add(value.value.lowercase())
}
}
}
}
}
override fun isSuppressed(request: SuppressRequest): Boolean {
// 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
val element = request.element
if (!element.isValid) return true
val file = element.containingFile
if (file is KtFile) {
if (file.doNotAnalyze != null) return true
}
if (request is DiagnosticSuppressRequest) {
for (suppressor in diagnosticSuppressors.get()) {
if (isSuppressedByExtension(suppressor, request.diagnostic)) return true
}
}
return super.isSuppressed(request)
}
override fun getClosestAnnotatedAncestorElement(element: PsiElement, rootElement: PsiElement, excludeSelf: Boolean): PsiElement? =
KtStubbedPsiUtil.getPsiOrStubParent(element, KtAnnotated::class.java, excludeSelf)
protected class DiagnosticSuppressRequest(val diagnostic: Diagnostic) : SuppressRequest {
override val element: PsiElement get() = diagnostic.psiElement
override val rootElement: PsiElement get() = element.containingFile
override val severity: Severity get() = diagnostic.severity
override val suppressKey: String get() = getDiagnosticSuppressKey(diagnostic)
}
companion object {
internal fun getDiagnosticSuppressKey(diagnostic: Diagnostic): String =
diagnostic.factory.name.lowercase()
}
}
class BindingContextSuppressCache(val context: BindingContext) : KotlinSuppressCache() {
override fun getSuppressionAnnotations(annotated: PsiElement): List {
val descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, annotated)
return descriptor?.annotations?.toList()
?: (annotated as? KtAnnotated)?.annotationEntries?.mapNotNull { context.get(BindingContext.ANNOTATION, it) }
?: emptyList()
}
override fun isSuppressedByExtension(suppressor: DiagnosticSuppressor, diagnostic: Diagnostic): Boolean {
return suppressor.isSuppressed(diagnostic, context)
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy