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
|
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 {
|
fun ir2stringWhole(ir: IrElement?, withDescriptors: Boolean = false): String {
|
||||||
val strWriter = StringWriter()
|
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.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi2ir.PsiErrorBuilder
|
||||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
@@ -66,6 +67,8 @@ class JvmBackendContext(
|
|||||||
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(methodSignatureMapper)
|
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(methodSignatureMapper)
|
||||||
override val sharedVariablesManager = JvmSharedVariablesManager(state.module, builtIns, irBuiltIns)
|
override val sharedVariablesManager = JvmSharedVariablesManager(state.module, builtIns, irBuiltIns)
|
||||||
|
|
||||||
|
val psiErrorBuilder = PsiErrorBuilder(psiSourceManager, state.diagnostics)
|
||||||
|
|
||||||
override val ir = JvmIr(irModuleFragment, this.symbolTable)
|
override val ir = JvmIr(irModuleFragment, this.symbolTable)
|
||||||
|
|
||||||
val irIntrinsics by lazy { IrIntrinsicMethods(irBuiltIns, ir.symbols) }
|
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.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
|
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
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.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
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.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
@@ -159,7 +161,9 @@ class IrSourceCompilerForInline(
|
|||||||
|
|
||||||
// TODO: Find a way to avoid using PSI here
|
// TODO: Find a way to avoid using PSI here
|
||||||
override fun reportSuspensionPointInsideMonitor(stackTraceElement: String) {
|
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
|
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
|
package org.jetbrains.kotlin.psi2ir
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
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.SourceManager
|
||||||
import org.jetbrains.kotlin.ir.SourceRangeInfo
|
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.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.util.fileOrNull
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
class PsiSourceManager : SourceManager {
|
class PsiSourceManager : SourceManager {
|
||||||
class PsiFileEntry(psiFile: PsiFile) : SourceManager.FileEntry {
|
class PsiFileEntry(psiFile: PsiFile) : SourceManager.FileEntry {
|
||||||
@@ -29,15 +38,12 @@ class PsiSourceManager : SourceManager {
|
|||||||
|
|
||||||
override val maxOffset: Int
|
override val maxOffset: Int
|
||||||
private val lineStartOffsets: IntArray
|
private val lineStartOffsets: IntArray
|
||||||
|
private val fileViewProvider = psiFile.viewProvider
|
||||||
|
|
||||||
init {
|
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
|
maxOffset = document.textLength
|
||||||
|
lineStartOffsets = IntArray(document.lineCount) { document.getLineStartOffset(it) }
|
||||||
lineStartOffsets = (0..document.lineCount - 1)
|
|
||||||
.map { document.getLineStartOffset(it) }
|
|
||||||
.toIntArray()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLineNumber(offset: Int): Int {
|
override fun getLineNumber(offset: Int): Int {
|
||||||
@@ -68,6 +74,20 @@ class PsiSourceManager : SourceManager {
|
|||||||
override val name: String get() = getRecognizableName()
|
override val name: String get() = getRecognizableName()
|
||||||
|
|
||||||
override fun toString(): String = 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>()
|
private val fileEntriesByKtFile = HashMap<KtFile, PsiFileEntry>()
|
||||||
@@ -97,4 +117,32 @@ class PsiSourceManager : SourceManager {
|
|||||||
|
|
||||||
override fun getFileEntry(irFile: IrFile): SourceManager.FileEntry? =
|
override fun getFileEntry(irFile: IrFile): SourceManager.FileEntry? =
|
||||||
fileEntriesByIrFile[irFile]
|
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