org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* 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.openapi.project.Project
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.extensions.ProjectExtensionDescriptor
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
interface DiagnosticSuppressor {
fun isSuppressed(diagnostic: Diagnostic): Boolean
fun isSuppressed(diagnostic: Diagnostic, bindingContext: BindingContext?): Boolean = isSuppressed(diagnostic)
companion object : ProjectExtensionDescriptor(
"org.jetbrains.kotlin.diagnosticSuppressor", DiagnosticSuppressor::class.java
) {
@Deprecated(
message = "This field is deprecated for compatibility reasons. Use ProjectExtensionDescriptor API instead",
replaceWith = ReplaceWith("DiagnosticSuppressor.extensionPointName"),
level = DeprecationLevel.WARNING
)
val EP_NAME: ExtensionPointName = extensionPointName
}
}
abstract class KotlinSuppressCache(project: Project?) : AbstractKotlinSuppressCache() {
private val diagnosticSuppressors: List = project?.let { DiagnosticSuppressor.getInstances(it) } ?: emptyList()
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) {
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(context.project) {
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)
}
}