[IR] Move KtDiagnosticReporterWithImplicitIrBasedContext to ir.tree

So that it could be accessible from the `ir.serialization.common` module
This commit is contained in:
Sergej Jaskiewicz
2024-01-19 15:25:43 +01:00
committed by Space Team
parent 6b6ed12df1
commit f88d09a2f6
11 changed files with 15 additions and 18 deletions
@@ -1,142 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin
import org.jetbrains.kotlin.backend.common.psi.PsiSourceManager
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.diagnostics.AbstractKotlinSuppressCache
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.diagnostics.KtDiagnosticReporterWithContext
import org.jetbrains.kotlin.ir.IrDiagnosticReporter
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.path
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.hasEqualFqName
import org.jetbrains.kotlin.ir.util.sourceElement
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.FqName
import java.util.*
class KtDiagnosticReporterWithImplicitIrBasedContext(
diagnosticReporter: DiagnosticReporter,
languageVersionSettings: LanguageVersionSettings
) : KtDiagnosticReporterWithContext(diagnosticReporter, languageVersionSettings), IrDiagnosticReporter {
private val suppressCache = IrBasedSuppressCache()
private fun IrElement.toSourceElement(containingIrFile: IrFile) =
(PsiSourceManager.findPsiElement(this, containingIrFile)?.let(::KtRealPsiSourceElement)
?: sourceElement())
override fun at(irElement: IrElement, containingIrDeclaration: IrDeclaration): DiagnosticContextImpl =
at(irElement, containingIrDeclaration.file)
override fun at(irDeclaration: IrDeclaration): DiagnosticContextImpl =
at(irDeclaration, irDeclaration.file)
override fun at(irElement: IrElement, containingIrFile: IrFile): DiagnosticContextImpl =
at(irElement.toSourceElement(containingIrFile), irElement, containingIrFile)
override fun at(
sourceElement: AbstractKtSourceElement?,
irElement: IrElement,
containingFile: IrFile
): DiagnosticContextImpl =
DiagnosticContextWithSuppressionImpl(sourceElement, irElement, containingFile)
override fun at(sourceElement: AbstractKtSourceElement?, containingFilePath: String): DiagnosticContextImpl {
error("Should not be called directly")
}
internal inner class DiagnosticContextWithSuppressionImpl(
sourceElement: AbstractKtSourceElement?,
private val irElement: IrElement,
private val containingFile: IrFile
) : DiagnosticContextImpl(sourceElement, containingFile.path) {
override fun isDiagnosticSuppressed(diagnostic: KtDiagnostic): Boolean =
suppressCache.isSuppressed(
irElement, containingFile, diagnostic.factory.name.lowercase(), diagnostic.severity
)
}
}
internal class IrBasedSuppressCache : AbstractKotlinSuppressCache<IrElement>() {
private val annotatedAncestorsPerRoot = mutableMapOf<IrElement, MutableMap<IrElement, IrElement>>()
private val annotationKeys = mutableMapOf<IrElement, Set<String>>()
@Synchronized
private fun ensureRootProcessed(rootElement: IrElement) =
annotatedAncestorsPerRoot.getOrPut(rootElement) {
val visitor = AnnotatedTreeVisitor()
rootElement.accept(visitor, Stack())
visitor.annotatedAncestors
}
private inner class AnnotatedTreeVisitor : IrElementVisitor<Unit, Stack<IrElement>> {
val annotatedAncestors = mutableMapOf<IrElement, IrElement>()
override fun visitElement(element: IrElement, data: Stack<IrElement>) {
if (data.isNotEmpty()) {
annotatedAncestors[element] = data.peek()
}
val isAnnotated = collectSuppressAnnotationKeys(element)
if (isAnnotated) {
data.push(element)
}
element.acceptChildren(this, data)
if (isAnnotated) {
data.pop()
}
}
private fun collectSuppressAnnotationKeys(element: IrElement): Boolean =
(element as? IrAnnotationContainer)?.annotations?.filter {
it.type.classOrNull?.owner?.hasEqualFqName(SUPPRESS) == true
}?.flatMap {
buildList {
fun addIfStringConst(irConst: IrConst<*>) {
if (irConst.kind == IrConstKind.String) {
add((irConst.value as String).lowercase())
}
}
for (i in 0 until it.valueArgumentsCount) {
when (val arg = it.getValueArgument(i)) {
is IrConst<*> -> addIfStringConst(arg)
is IrConstantArray -> arg.elements.filterIsInstance<IrConstantPrimitive>().forEach {
addIfStringConst(it.value)
}
// TODO: consider leaving only this branch
is IrVararg -> arg.elements.filterIsInstance<IrConst<*>>().forEach {
addIfStringConst(it)
}
}
}
}
}?.takeIf { it.isNotEmpty() }?.also {
annotationKeys[element] = it.toSet()
} != null
}
override fun getClosestAnnotatedAncestorElement(element: IrElement, rootElement: IrElement, excludeSelf: Boolean): IrElement? {
val annotatedAncestors = ensureRootProcessed(rootElement)
return if (!excludeSelf && annotationKeys.containsKey(element)) element else annotatedAncestors[element]
}
override fun getSuppressingStrings(annotated: IrElement): Set<String> = annotationKeys[annotated].orEmpty()
}
private val SUPPRESS = FqName("kotlin.Suppress")
@@ -1,42 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.psi
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.PsiIrFileEntry
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.util.fileOrNull
import kotlin.reflect.KClass
object PsiSourceManager {
fun <E : PsiElement> findPsiElement(irElement: IrElement, irFile: IrFile, psiElementClass: KClass<E>): E? {
val psiFileEntry = irFile.fileEntry as? PsiIrFileEntry ?: return null
return psiFileEntry.findPsiElement(irElement, psiElementClass)
}
fun findPsiElement(irElement: IrElement, irFile: IrFile): PsiElement? {
val psiFileEntry = irFile.fileEntry as? PsiIrFileEntry ?: return null
return psiFileEntry.findPsiElement(irElement)
}
fun <E : PsiElement> findPsiElement(irElement: IrElement, irDeclaration: IrDeclaration, psiElementClass: KClass<E>): E? {
val irFile = irDeclaration.fileOrNull ?: return null
return findPsiElement(irElement, irFile, psiElementClass)
}
fun findPsiElement(irElement: IrElement, irDeclaration: IrDeclaration): PsiElement? {
val irFile = irDeclaration.fileOrNull ?: return null
return findPsiElement(irElement, irFile)
}
fun <E : PsiElement> findPsiElement(irDeclaration: IrDeclaration, psiElementClass: KClass<E>): E? =
findPsiElement(irDeclaration, irDeclaration, psiElementClass)
fun findPsiElement(irDeclaration: IrDeclaration): PsiElement? =
findPsiElement(irDeclaration, irDeclaration)
}