PsiErrorBuilder - error reporting abstraction for JVM_IR
This commit is contained in:
@@ -42,7 +42,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Descriptor
|
||||
import java.io.StringWriter
|
||||
|
||||
|
||||
fun ir2string(ir: IrElement?): String = ir2stringWhole(ir).takeWhile { it != '\n' }
|
||||
fun ir2string(ir: IrElement?): String = ir?.render() ?: ""
|
||||
|
||||
fun ir2stringWhole(ir: IrElement?, withDescriptors: Boolean = false): String {
|
||||
val strWriter = StringWriter()
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.PsiErrorBuilder
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -66,6 +67,8 @@ class JvmBackendContext(
|
||||
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(methodSignatureMapper)
|
||||
override val sharedVariablesManager = JvmSharedVariablesManager(state.module, builtIns, irBuiltIns)
|
||||
|
||||
val psiErrorBuilder = PsiErrorBuilder(psiSourceManager, state.diagnostics)
|
||||
|
||||
override val ir = JvmIr(irModuleFragment, this.symbolTable)
|
||||
|
||||
val irIntrinsics by lazy { IrIntrinsicMethods(irBuiltIns, ir.symbols) }
|
||||
|
||||
+5
-1
@@ -24,11 +24,13 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.SUSPENSION_POINT_INSIDE_MONITOR
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -159,7 +161,9 @@ class IrSourceCompilerForInline(
|
||||
|
||||
// TODO: Find a way to avoid using PSI here
|
||||
override fun reportSuspensionPointInsideMonitor(stackTraceElement: String) {
|
||||
org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor(findElement()!!, state, stackTraceElement)
|
||||
codegen.context.psiErrorBuilder
|
||||
.at(callElement.symbol.owner as IrDeclaration)
|
||||
.report(SUSPENSION_POINT_INSIDE_MONITOR, stackTraceElement)
|
||||
}
|
||||
|
||||
private fun findElement() = (callElement.symbol.descriptor.original as? DeclarationDescriptorWithSource)?.source?.getPsi() as? KtElement
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.psi2ir
|
||||
|
||||
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 psiSourceManager: PsiSourceManager,
|
||||
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(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> report(diagnosticFactory: DiagnosticFactory1<E, A>, a: A) {
|
||||
diagnosticSink.report(diagnosticFactory.on(psiElement, a))
|
||||
}
|
||||
|
||||
fun <A, B> report(diagnosticFactory: DiagnosticFactory2<E, A, B>, a: A, b: B) {
|
||||
diagnosticSink.report(diagnosticFactory.on(psiElement, a, b))
|
||||
}
|
||||
|
||||
fun <A, B, C> report(diagnosticFactory: DiagnosticFactory3<E, A, B, C>, a: A, b: B, c: C) {
|
||||
diagnosticSink.report(diagnosticFactory.on(psiElement, a, b, c))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.SourceRangeInfo
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.util.fileOrNull
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import java.util.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class PsiSourceManager : SourceManager {
|
||||
class PsiFileEntry(psiFile: PsiFile) : SourceManager.FileEntry {
|
||||
@@ -29,15 +38,12 @@ class PsiSourceManager : SourceManager {
|
||||
|
||||
override val maxOffset: Int
|
||||
private val lineStartOffsets: IntArray
|
||||
private val fileViewProvider = psiFile.viewProvider
|
||||
|
||||
init {
|
||||
val document = psiFile.viewProvider.document ?: throw AssertionError("No document for $psiFile")
|
||||
|
||||
val document = fileViewProvider.document ?: throw AssertionError("No document for $psiFile")
|
||||
maxOffset = document.textLength
|
||||
|
||||
lineStartOffsets = (0..document.lineCount - 1)
|
||||
.map { document.getLineStartOffset(it) }
|
||||
.toIntArray()
|
||||
lineStartOffsets = IntArray(document.lineCount) { document.getLineStartOffset(it) }
|
||||
}
|
||||
|
||||
override fun getLineNumber(offset: Int): Int {
|
||||
@@ -68,6 +74,20 @@ class PsiSourceManager : SourceManager {
|
||||
override val name: String get() = getRecognizableName()
|
||||
|
||||
override fun toString(): String = getRecognizableName()
|
||||
|
||||
fun findPsiElement(irElement: IrElement): PsiElement? {
|
||||
var psiElement = fileViewProvider.findElementAt(irElement.startOffset)
|
||||
while (psiElement != null) {
|
||||
if (psiElement.endOffset == irElement.endOffset) break
|
||||
psiElement = psiElement.parent
|
||||
}
|
||||
return psiElement
|
||||
}
|
||||
|
||||
fun <E : PsiElement> findPsiElement(irElement: IrElement, psiElementClass: KClass<E>): E? =
|
||||
findPsiElement(irElement)?.let {
|
||||
PsiTreeUtil.getParentOfType(it, psiElementClass.java, false)
|
||||
}
|
||||
}
|
||||
|
||||
private val fileEntriesByKtFile = HashMap<KtFile, PsiFileEntry>()
|
||||
@@ -97,4 +117,32 @@ class PsiSourceManager : SourceManager {
|
||||
|
||||
override fun getFileEntry(irFile: IrFile): SourceManager.FileEntry? =
|
||||
fileEntriesByIrFile[irFile]
|
||||
|
||||
fun <E : PsiElement> findPsiElement(irElement: IrElement, irFile: IrFile, psiElementClass: KClass<E>): E? {
|
||||
val psiFileEntry = fileEntriesByIrFile[irFile]
|
||||
?: throw AssertionError("No PSI file for irFile $irFile")
|
||||
return psiFileEntry.findPsiElement(irElement, psiElementClass)
|
||||
}
|
||||
|
||||
fun findPsiElement(irElement: IrElement, irFile: IrFile): PsiElement? {
|
||||
val psiFileEntry = fileEntriesByIrFile[irFile]
|
||||
?: throw AssertionError("No PSI file for irFile $irFile")
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user