Report IR errors via new diagnostic infrastructure

This commit is contained in:
Ilya Chernikov
2021-09-28 19:15:23 +02:00
parent 21ea92cd4a
commit 1e056a7aa8
13 changed files with 216 additions and 102 deletions
@@ -0,0 +1,63 @@
/*
* 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.sourceElement
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.util.file
class KtDiagnosticReporterWithImplicitIrBasedContext(
val diagnosticReporter: DiagnosticReporter,
val languageVersionSettings: LanguageVersionSettings
) : DiagnosticReporter() {
override fun report(diagnostic: KtDiagnostic?, context: DiagnosticContext) = diagnosticReporter.report(diagnostic, context)
fun at(irElement: IrElement, containingIrFile: IrFile): DiagnosticContextOverIr =
DiagnosticContextOverIr(irElement, containingIrFile)
fun at(irElement: IrElement, containingIrDeclaration: IrDeclaration): DiagnosticContextOverIr =
DiagnosticContextOverIr(irElement, containingIrDeclaration)
fun at(irDeclaration: IrDeclaration): DiagnosticContextOverIr =
DiagnosticContextOverIr(irDeclaration, irDeclaration)
@Suppress("UNUSED_PARAMETER")
inner class DiagnosticContextOverIr(irElement: IrElement, containingIrFile: IrFile) : DiagnosticContext {
constructor(irElement: IrElement, containingIrDeclaration: IrDeclaration): this(irElement, containingIrDeclaration.file)
val sourceElement = irElement.sourceElement()
override fun isDiagnosticSuppressed(diagnostic: KtDiagnostic): Boolean {
TODO("Not yet implemented")
}
override val languageVersionSettings: LanguageVersionSettings
get() = this@KtDiagnosticReporterWithImplicitIrBasedContext.languageVersionSettings
@OptIn(InternalDiagnosticFactoryMethod::class)
fun report(
factory: KtDiagnosticFactory0,
positioningStrategy: AbstractSourceElementPositioningStrategy? = null
) {
sourceElement?.let { report(factory.on(it, positioningStrategy), this) }
}
@OptIn(InternalDiagnosticFactoryMethod::class)
fun <A : Any> report(
factory: KtDiagnosticFactory1<A>,
a: A,
positioningStrategy: AbstractSourceElementPositioningStrategy? = null
) {
sourceElement?.let { report(factory.on(it, a, positioningStrategy), this) }
}
}
}
@@ -16,8 +16,16 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.AbstractKtSourceElement
import org.jetbrains.kotlin.KtOffsetsOnlySourceElement
import org.jetbrains.kotlin.KtRealPsiSourceElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.backend.common.psi.PsiSourceManager
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.util.render
fun CommonBackendContext.reportWarning(message: String, irFile: IrFile?, irElement: IrElement) {
report(irElement, irFile, message, false)
@@ -28,3 +36,13 @@ fun <E> MutableList<E>.push(element: E) = this.add(element)
fun <E> MutableList<E>.pop() = this.removeAt(size - 1)
fun <E> MutableList<E>.peek(): E? = if (size == 0) null else this[size - 1]
fun findKtSourceElement(irElement: IrElement, irDeclaration: IrDeclaration): KtSourceElement {
val psiElement = PsiSourceManager.findPsiElement(irElement, irDeclaration)
?: throw AssertionError("No PsiElement found for '${irElement.render()}'")
return KtRealPsiSourceElement(psiElement)
}
fun IrElement.sourceElement(): AbstractKtSourceElement? =
if (startOffset != UNDEFINED_OFFSET) KtOffsetsOnlySourceElement(this.startOffset, this.endOffset)
else null
@@ -1,72 +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.diagnostics.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.util.render
import kotlin.reflect.KClass
class PsiErrorBuilder(private val diagnosticSink: DiagnosticSink) {
fun <E : PsiElement> at(irDeclaration: IrDeclaration, psiElementClass: KClass<E>): Location<E> =
Location(
PsiSourceManager.findPsiElement(irDeclaration, psiElementClass)
?: throw AssertionError("No ${psiElementClass.simpleName} found for '${irDeclaration.render()}'")
)
fun at(irDeclaration: IrDeclaration): Location<PsiElement> =
Location(
PsiSourceManager.findPsiElement(irDeclaration)
?: throw AssertionError("No PsiElement found for '${irDeclaration.render()}'")
)
fun <E : PsiElement> at(psiElement: E) = Location(psiElement)
fun <E : PsiElement> at(irElement: IrElement, irDeclaration: IrDeclaration, psiElementClass: KClass<E>): Location<E> =
Location(
PsiSourceManager.findPsiElement(irElement, irDeclaration, psiElementClass)
?: throw AssertionError("No ${psiElementClass.simpleName} found for '${irElement.render()}'")
)
fun at(irElement: IrElement, irDeclaration: IrDeclaration): Location<PsiElement> =
Location(
PsiSourceManager.findPsiElement(irElement, irDeclaration)
?: throw AssertionError("No PsiElement found for '${irElement.render()}'")
)
fun <E : PsiElement> at(irElement: IrElement, irFile: IrFile, psiElementClass: KClass<E>): Location<E> =
Location(
PsiSourceManager.findPsiElement(irElement, irFile, psiElementClass)
?: throw AssertionError("No ${psiElementClass.simpleName} found for '${irElement.render()}'")
)
fun at(irElement: IrElement, irFile: IrFile): Location<PsiElement> =
Location(
PsiSourceManager.findPsiElement(irElement, irFile)
?: throw AssertionError("No PsiElement found for '${irElement.render()}'")
)
inner class Location<E : PsiElement>(private val psiElement: E) {
fun report(diagnosticFactory: DiagnosticFactory0<E>) {
diagnosticSink.report(diagnosticFactory.on(psiElement))
}
fun <A : Any> report(diagnosticFactory: DiagnosticFactory1<E, A>, a: A) {
diagnosticSink.report(diagnosticFactory.on(psiElement, a))
}
fun <A : Any, B : Any> report(diagnosticFactory: DiagnosticFactory2<E, A, B>, a: A, b: B) {
diagnosticSink.report(diagnosticFactory.on(psiElement, a, b))
}
fun <A : Any, B : Any, C : Any> report(diagnosticFactory: DiagnosticFactory3<E, A, B, C>, a: A, b: B, c: C) {
diagnosticSink.report(diagnosticFactory.on(psiElement, a, b, c))
}
}
}