[Analysis API] do not create multiple attachments inside exceptions

This commit is contained in:
Ilya Kirillov
2022-08-03 10:46:16 +02:00
parent ddbd89aea7
commit f45f1ba3dc
30 changed files with 319 additions and 278 deletions
@@ -15,10 +15,9 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
@OptIn(KtAnalysisApiInternals::class)
class KtFirAnalysisSessionProvider(project: Project) : CachingKtAnalysisSessionProvider<LLFirResolveSession>(project) {
@@ -29,7 +28,7 @@ class KtFirAnalysisSessionProvider(project: Project) : CachingKtAnalysisSessionP
override fun getFirResolveSession(contextSymbol: KtSymbol): LLFirResolveSession {
return when (contextSymbol) {
is KtFirSymbol<*> -> contextSymbol.firResolveSession
else -> errorWithAttachment("Invalid symbol") {
else -> buildErrorWithAttachment("Invalid symbol") {
withSymbolAttachment("symbol", contextSymbol)
}
}
@@ -20,10 +20,10 @@ import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withConeTypeAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withConeTypeEntry
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolEntry
import org.jetbrains.kotlin.analysis.providers.createPackageProvider
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import org.jetbrains.kotlin.fir.*
@@ -53,7 +53,7 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
@@ -210,7 +210,7 @@ internal class KtSymbolByFirBuilder constructor(
if (firSymbol.dispatchReceiverType?.contains { it is ConeStubType } == true) {
return buildFunctionSymbol(
firSymbol.originalIfFakeOverride()
?: firErrorWithAttachment("Stub type in real declaration", fir = firSymbol.fir)
?: errorWithFirSpecificEntries("Stub type in real declaration", fir = firSymbol.fir)
)
}
@@ -588,20 +588,20 @@ internal class KtSymbolByFirBuilder constructor(
companion object {
private fun throwUnexpectedElementError(element: FirBasedSymbol<*>): Nothing {
errorWithAttachment("Unexpected ${element::class.simpleName}") {
withFirSymbolAttachment("firSymbol", element)
buildErrorWithAttachment("Unexpected ${element::class.simpleName}") {
withFirSymbolEntry("firSymbol", element)
}
}
private fun throwUnexpectedElementError(element: FirElement): Nothing {
errorWithAttachment("Unexpected ${element::class.simpleName}") {
withFirAttachment("firElement", element)
buildErrorWithAttachment("Unexpected ${element::class.simpleName}") {
withFirEntry("firElement", element)
}
}
private fun throwUnexpectedElementError(element: ConeKotlinType): Nothing {
errorWithAttachment("Unexpected ${element::class.simpleName}") {
withConeTypeAttachment("coneType", element)
buildErrorWithAttachment("Unexpected ${element::class.simpleName}") {
withConeTypeEntry("coneType", element)
}
}
@@ -25,9 +25,8 @@ import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
@@ -69,7 +68,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
internal class KtFirCallResolver(
override val analysisSession: KtFirAnalysisSession,
@@ -155,7 +155,7 @@ internal class KtFirCallResolver(
when (val calleeReference = calleeReference) {
is FirResolvedNamedReference -> {
val call = createKtCall(psi, this, null, resolveFragmentOfCall)
?: firErrorWithAttachment("expect `createKtCall` to succeed for resolvable case", fir = this, psi = psi)
?: errorWithFirSpecificEntries("expect `createKtCall` to succeed for resolvable case", fir = this, psi = psi)
KtSuccessCallInfo(call)
}
is FirErrorNamedReference -> {
@@ -1167,9 +1167,9 @@ internal class KtFirCallResolver(
}
override fun unresolvedKtCallError(psi: KtElement): Nothing {
errorWithAttachment("${psi::class.simpleName}(${psi::class.simpleName}) should always resolve to a KtCallInfo") {
withPsiAttachment("psi", psi)
psi.getOrBuildFir(firResolveSession)?.let { withFirAttachment("fir", it) }
buildErrorWithAttachment("${psi::class.simpleName}(${psi::class.simpleName}) should always resolve to a KtCallInfo") {
withPsiEntry("psi", psi)
psi.getOrBuildFir(firResolveSession)?.let { withFirEntry("fir", it) }
}
}
}
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
internal class KtFirSymbolContainingDeclarationProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -87,7 +87,7 @@ internal class KtFirSymbolContainingDeclarationProvider(
private fun getContainingPsi(symbol: KtFirSymbol<*>): KtDeclaration {
val source = symbol.firSymbol.source
val thisSource = when (source?.kind) {
null -> errorWithAttachment("PSI should present for declaration built by Kotlin code") {
null -> buildErrorWithAttachment("PSI should present for declaration built by Kotlin code") {
withSymbolAttachment("symbolForContainingPsi", symbol)
}
@@ -99,19 +99,19 @@ internal class KtFirSymbolContainingDeclarationProvider(
KtFakeSourceElementKind.ItLambdaParameter -> return source.psi as KtFunctionLiteral
KtRealSourceElementKind -> source.psi!!
else ->
errorWithAttachment("errorWithAttachment FirSourceElement: kind=${source.kind} element=${source.psi!!::class.simpleName}") {
buildErrorWithAttachment("errorWithAttachment FirSourceElement: kind=${source.kind} element=${source.psi!!::class.simpleName}") {
withSymbolAttachment("symbolForContainingPsi", symbol)
}
}
return when (symbol.origin) {
KtSymbolOrigin.SOURCE -> thisSource.getContainingKtDeclaration()
?: errorWithAttachment("Containing declaration should present for non-toplevel declaration") {
?: buildErrorWithAttachment("Containing declaration should present for non-toplevel declaration") {
withSymbolAttachment("symbolForContainingPsi", symbol)
}
KtSymbolOrigin.SOURCE_MEMBER_GENERATED -> thisSource as KtDeclaration
else -> errorWithAttachment("Unsupported declaration origin ${symbol.origin}") {
else -> buildErrorWithAttachment("Unsupported declaration origin ${symbol.origin}") {
withSymbolAttachment("symbolForContainingPsi", symbol)
}
}
@@ -128,7 +128,7 @@ internal class KtFirSymbolContainingDeclarationProvider(
check(symbol.symbolKind == KtSymbolKind.CLASS_MEMBER)
fun error(message: String): Nothing {
errorWithAttachment(message) {
buildErrorWithAttachment(message) {
withSymbolAttachment("symbolToGetContaining", symbol)
}
}
@@ -11,8 +11,8 @@ import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAcces
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectData
import org.jetbrains.kotlin.fir.scopes.impl.originalForWrappedIntegerOperator
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
internal interface KtFirSymbol<out S : FirBasedSymbol<*>> : KtSymbol, KtLifetimeOwner {
val firSymbol: S
@@ -63,16 +63,16 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori
is FirSyntheticProperty,
is FirSyntheticPropertyAccessor -> KtSymbolOrigin.JAVA_SYNTHETIC_PROPERTY
else -> errorWithAttachment("Invalid FirDeclarationOrigin ${origin::class.simpleName}") {
withFirAttachment("firToGetOrigin", this@ktSymbolOrigin)
else -> buildErrorWithAttachment("Invalid FirDeclarationOrigin ${origin::class.simpleName}") {
withFirEntry("firToGetOrigin", this@ktSymbolOrigin)
}
}
}
FirDeclarationOrigin.ImportedFromObject -> {
val importedFromObjectData = (this as FirCallableDeclaration).importedFromObjectData
?: errorWithAttachment("Declaration has ImportedFromObject origin, but no importedFromObjectData present") {
withFirAttachment("firToGetOrigin", this@ktSymbolOrigin)
?: buildErrorWithAttachment("Declaration has ImportedFromObject origin, but no importedFromObjectData present") {
withFirEntry("firToGetOrigin", this@ktSymbolOrigin)
}
importedFromObjectData.original.ktSymbolOrigin()
@@ -80,7 +80,7 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori
FirDeclarationOrigin.WrappedIntegerOperator -> {
val original = (this as FirSimpleFunction).originalForWrappedIntegerOperator?.fir
?: firErrorWithAttachment(
?: errorWithFirSpecificEntries(
"Declaration has WrappedIntegerOperator origin, but no originalForWrappedIntegerOperator present",
fir = this
)
@@ -91,7 +91,7 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori
is FirDeclarationOrigin.Plugin -> KtSymbolOrigin.PLUGIN
FirDeclarationOrigin.RenamedForOverride -> KtSymbolOrigin.JAVA
FirDeclarationOrigin.SubstitutionOverride -> KtSymbolOrigin.SUBSTITUTION_OVERRIDE
FirDeclarationOrigin.DynamicScope -> errorWithAttachment("Invalid FirDeclarationOrigin ${origin::class.simpleName}") {
withFirAttachment("firToGetOrigin", this@ktSymbolOrigin)
FirDeclarationOrigin.DynamicScope -> buildErrorWithAttachment("Invalid FirDeclarationOrigin ${origin::class.simpleName}") {
withFirEntry("firToGetOrigin", this@ktSymbolOrigin)
}
}
@@ -10,21 +10,18 @@ import org.jetbrains.kotlin.analysis.api.fir.components.KtFirAnalysisSessionComp
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbolOfType
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiAttachment
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolEntry
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
internal class KtFirSymbolProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -33,7 +30,7 @@ internal class KtFirSymbolProvider(
override fun getParameterSymbol(psi: KtParameter): KtVariableLikeSymbol {
return when {
psi.isFunctionTypeParameter -> firErrorWithAttachment(
psi.isFunctionTypeParameter -> errorWithFirSpecificEntries(
"Creating KtValueParameterSymbol for function type parameter is not possible. Please see the KDoc of getParameterSymbol",
psi = psi,
)
@@ -69,9 +66,9 @@ internal class KtFirSymbolProvider(
}
is FirAnonymousFunctionSymbol -> firSymbolBuilder.functionLikeBuilder.buildAnonymousFunctionSymbol(firSymbol)
else -> errorWithAttachment("Unexpected ${firSymbol::class}") {
withFirSymbolAttachment("firSymbol", firSymbol)
withPsiAttachment("function", psi)
else -> buildErrorWithAttachment("Unexpected ${firSymbol::class}") {
withFirSymbolEntry("firSymbol", firSymbol)
withPsiEntry("function", psi)
}
}
}
@@ -137,9 +134,9 @@ internal class KtFirSymbolProvider(
private fun KtClassOrObject.resolveToFirClassLikeSymbol(): FirClassSymbol<*> {
return when (val firClassLike = resolveToFirSymbolOfType<FirClassLikeSymbol<*>>(firResolveSession)) {
is FirTypeAliasSymbol -> firClassLike.fullyExpandedClass(firResolveSession.useSiteFirSession)
?: errorWithAttachment("${firClassLike.fir::class} should be expanded to the expected type alias") {
withFirSymbolAttachment("firClassLikeSymbol", firClassLike)
withPsiAttachment("ktClassOrObject", this@resolveToFirClassLikeSymbol)
?: buildErrorWithAttachment("${firClassLike.fir::class} should be expanded to the expected type alias") {
withFirSymbolEntry("firClassLikeSymbol", firClassLike)
withPsiEntry("ktClassOrObject", this@resolveToFirClassLikeSymbol)
}
is FirAnonymousObjectSymbol -> firClassLike
is FirRegularClassSymbol -> firClassLike
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.analysis.api.types.KtFunctionalType
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
@@ -33,7 +33,7 @@ internal class KtFirFunctionalType(
override val classId: ClassId get() = withValidityAssertion { coneType.lookupTag.classId }
override val classSymbol: KtClassLikeSymbol by cached {
builder.classifierBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag)
?: firErrorWithAttachment("Class was not found", coneType = coneType)
?: errorWithFirSpecificEntries("Class was not found", coneType = coneType)
}
override val typeArguments: List<KtTypeArgument> by cached {
coneType.typeArguments.map { typeArgument ->
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
import org.jetbrains.kotlin.analysis.api.types.KtTypeParameterType
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
import org.jetbrains.kotlin.fir.types.renderForDebugging
import org.jetbrains.kotlin.name.Name
@@ -27,7 +27,7 @@ internal class KtFirTypeParameterType(
override val name: Name get() = withValidityAssertion { coneType.lookupTag.name }
override val symbol: KtTypeParameterSymbol by cached {
builder.classifierBuilder.buildTypeParameterSymbolByLookupTag(coneType.lookupTag)
?: firErrorWithAttachment("Type parameter was not found", coneType = coneType)
?: errorWithFirSpecificEntries("Type parameter was not found", coneType = coneType)
}
override val annotationsList: KtAnnotationsList by cached {
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
import org.jetbrains.kotlin.analysis.api.types.KtUsualClassType
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.renderForDebugging
import org.jetbrains.kotlin.name.ClassId
@@ -28,7 +28,7 @@ internal class KtFirUsualClassType(
override val classId: ClassId get() = withValidityAssertion { coneType.lookupTag.classId }
override val classSymbol: KtClassLikeSymbol by cached {
builder.classifierBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag)
?: firErrorWithAttachment("Class was not found", coneType = coneType)
?: errorWithFirSpecificEntries("Class was not found", coneType = coneType)
}
override val typeArguments: List<KtTypeArgument> by cached {
coneType.typeArguments.map { typeArgument ->
@@ -8,19 +8,18 @@ package org.jetbrains.kotlin.analysis.api.fir.utils
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.utils.errors.ExceptionAttachmentBuilder
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.withAttachmentDetailed
fun KotlinExceptionWithAttachments.withSymbolAttachment(name: String, symbol: KtSymbol): KotlinExceptionWithAttachments {
withAttachmentDetailed(name, symbol, DebugSymbolRenderer::render)
withPsiAttachment("${name}Psi", symbol.psi)
fun ExceptionAttachmentBuilder.withSymbolAttachment(name: String, symbol: KtSymbol) {
withEntry(name, symbol, DebugSymbolRenderer::render)
withPsiEntry("${name}Psi", symbol.psi)
if (symbol is KtFirSymbol<*>) {
val symbolFir = symbol.firSymbol.fir
withFirAttachment("${name}Fir", symbolFir)
withFirEntry("${name}Fir", symbolFir)
}
return this
}
@@ -8,12 +8,12 @@ package org.jetbrains.kotlin.analysis.api.components
import org.jetbrains.kotlin.analysis.api.calls.KtCallCandidateInfo
import org.jetbrains.kotlin.analysis.api.calls.KtCallInfo
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.utils.errors.withPsiAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtUnaryExpression
import org.jetbrains.kotlin.utils.errorWithAttachment
public abstract class KtCallResolver : KtAnalysisSessionComponent() {
public abstract fun resolveCall(psi: KtElement): KtCallInfo?
@@ -21,8 +21,8 @@ public abstract class KtCallResolver : KtAnalysisSessionComponent() {
public abstract fun collectCallCandidates(psi: KtElement): List<KtCallCandidateInfo>
public open fun unresolvedKtCallError(psi: KtElement): Nothing {
errorWithAttachment("${psi::class.simpleName}(${psi::class.simpleName}) should always resolve to a KtCallInfo") {
withPsiAttachment("psi", psi)
buildErrorWithAttachment("${psi::class.simpleName}(${psi::class.simpleName}) should always resolve to a KtCallInfo") {
withPsiEntry("psi", psi)
}
}
}
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2022 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.analysis.utils.errors
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
public class ExceptionAttachmentBuilder {
private val printer = PrettyPrinter()
public fun <T> withEntry(name: String, value: T, render: (T & Any) -> String) {
withEntry(name) {
appendLine("Class: ${value?.let { it::class.java.name }}")
appendLine("Value:")
withIndent {
appendLine(value?.let(render) ?: "null")
}
}
}
public fun withEntry(name: String, value: String?) {
with(printer) {
appendLine("- $name:")
withIndent {
appendLine(value)
}
appendLine(separator)
}
}
public fun withEntry(name: String, buildValue: PrettyPrinter.() -> Unit) {
withEntry(name, prettyPrint { buildValue() })
}
public fun withEntryGroup(groupName: String, build: ExceptionAttachmentBuilder.() -> Unit) {
val builder = ExceptionAttachmentBuilder().apply(build)
withEntry(groupName, builder) { it.buildString() }
}
public fun buildString(): String = printer.toString()
private companion object {
private const val separator = "========"
}
}
public inline fun KotlinExceptionWithAttachments.buildAttachment(
name: String = "info.txt",
buildContent: ExceptionAttachmentBuilder.() -> Unit
): KotlinExceptionWithAttachments {
return withAttachment(name, ExceptionAttachmentBuilder().apply(buildContent).buildString())
}
public inline fun buildErrorWithAttachment(
message: String,
cause: Throwable? = null,
attachmentName: String = "info.txt",
buildAttachment: ExceptionAttachmentBuilder.() -> Unit = {}
): Nothing {
val exception = KotlinExceptionWithAttachments(message, cause)
exception.buildAttachment(attachmentName) { buildAttachment() }
throw exception
}
@OptIn(ExperimentalContracts::class)
public inline fun checkWithAttachmentBuilder(
value: Boolean,
lazyMessage: () -> String,
buildAttachment: ExceptionAttachmentBuilder.() -> Unit = {}
) {
contract { returns() implies (value) }
if (!value) {
buildErrorWithAttachment(lazyMessage(), buildAttachment = buildAttachment)
}
}
@@ -1,33 +0,0 @@
/*
* Copyright 2010-2022 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.analysis.utils.errors
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.utils.withAttachmentDetailed
public fun unexpectedElementError(elementName: String, element: Any?): Nothing {
errorWithAttachment("Unexpected $elementName ${element?.let { it::class.simpleName }}") {
withAttachment("element", element)
}
}
public inline fun <reified ELEMENT> unexpectedElementError(element: Any?): Nothing {
unexpectedElementError(ELEMENT::class.simpleName ?: ELEMENT::class.java.name, element)
}
public fun KotlinExceptionWithAttachments.withPsiAttachment(name: String, psi: PsiElement?): KotlinExceptionWithAttachments {
withAttachmentDetailed(name, psi) { psiElement ->
when (psiElement) {
is KtElement -> psiElement.getElementTextInContext()
else -> psiElement.text
}
}
return this
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2022 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.analysis.utils.errors
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.psi.KtElement
public fun ExceptionAttachmentBuilder.withPsiEntry(name: String, psi: PsiElement?) {
withEntry(name, psi) { psiElement ->
when (psiElement) {
is KtElement -> psiElement.getElementTextInContext()
else -> psiElement.text
}
}
}
public fun ExceptionAttachmentBuilder.withClassEntry(name: String, element: Any?) {
withEntry(name, element) { it::class.java.name }
}
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2022 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.analysis.utils.errors
public fun unexpectedElementError(elementName: String, element: Any?): Nothing {
buildErrorWithAttachment("Unexpected $elementName ${element?.let { it::class.simpleName }}") {
withEntry(elementName, element) { element.toString() }
}
}
public inline fun <reified ELEMENT> unexpectedElementError(element: Any?): Nothing {
unexpectedElementError(ELEMENT::class.simpleName ?: ELEMENT::class.java.name, element)
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
abstract class ContextByDesignationCollector<C : Any>(private val designation: FirDeclarationDesignation) {
private var context: C? = null
@@ -57,7 +57,7 @@ private class FirDesignationState(val designation: FirDeclarationDesignation) {
val currentDeclaration: FirDeclaration
get() = currentDeclarationIfPresent
?: firErrorWithAttachment("Went inside target declaration")
?: errorWithFirSpecificEntries("Went inside target declaration")
fun goNext() {
if (canGoNext()) {
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirLibraryOrLibra
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirNotUnderContentRootResolvableResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.project.structure.*
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
import org.jetbrains.kotlin.analysis.utils.caches.strongCachedValue
@@ -87,8 +87,8 @@ internal class LLFirResolveSessionService(project: Project) {
}
else -> {
firErrorWithAttachment("Unexpected ${useSiteKtModule::class.java}") {
withAttachment("module", useSiteKtModule.moduleDescription)
errorWithFirSpecificEntries("Unexpected ${useSiteKtModule::class.java}") {
withEntry("module", useSiteKtModule) { it.moduleDescription }
}
}
}
@@ -5,21 +5,19 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.api
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getContainingFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
import org.jetbrains.kotlin.utils.checkWithAttachment
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder
class FirDeclarationDesignationWithFile(
path: List<FirDeclaration>,
@@ -80,8 +78,8 @@ private fun collectDesignationPath(declaration: FirDeclaration): List<FirDeclara
else -> return null
} ?: return emptyList()
checkWithAttachment(containingClass is FirRegularClass, { "FirRegularClass as containing declaration expected" }) {
it.withFirAttachment("containingClassFir", containingClass)
checkWithAttachmentBuilder(containingClass is FirRegularClass, { "FirRegularClass as containing declaration expected" }) {
withFirEntry("containingClassFir", containingClass)
}
return if (!containingClass.isLocal) containingClass.collectForNonLocal().asReversed() else null
}
@@ -92,20 +90,20 @@ private fun ConeClassLikeLookupTag.toFirRegularClassFromSameSession(useSiteSessi
}
fun FirDeclaration.collectDesignation(firFile: FirFile): FirDeclarationDesignationWithFile =
tryCollectDesignation(firFile) ?: errorWithAttachment("No designation of local declaration") {
withFirAttachment("firFile", firFile)
tryCollectDesignation(firFile) ?: buildErrorWithAttachment("No designation of local declaration") {
withFirEntry("firFile", firFile)
}
fun FirDeclaration.collectDesignation(): FirDeclarationDesignation =
tryCollectDesignation()
?: errorWithAttachment("No designation of local declaration") {
withFirAttachment("FirDeclaration", this@collectDesignation)
?: buildErrorWithAttachment("No designation of local declaration") {
withFirEntry("FirDeclaration", this@collectDesignation)
}
fun FirDeclaration.collectDesignationWithFile(): FirDeclarationDesignationWithFile =
tryCollectDesignationWithFile()
?: errorWithAttachment("No designation of local declaration") {
withFirAttachment("FirDeclaration", this@collectDesignationWithFile)
?: buildErrorWithAttachment("No designation of local declaration") {
withFirEntry("FirDeclaration", this@collectDesignationWithFile)
}
fun FirDeclaration.tryCollectDesignation(firFile: FirFile): FirDeclarationDesignationWithFile? =
@@ -5,15 +5,15 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.api
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withConeTypeAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withConeTypeEntry
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolEntry
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.withAttachmentDetailed
import org.jetbrains.kotlin.analysis.utils.errors.*
import java.util.*
import kotlin.reflect.KClass
@@ -23,12 +23,14 @@ class InvalidFirElementTypeException(
expectedFirClasses: List<KClass<*>>,
) : KotlinExceptionWithAttachments("") {
init {
when (actualFirElement) {
is FirElement -> withFirAttachment("firElement", actualFirElement)
is FirBasedSymbol<*> -> withFirSymbolAttachment("firSymbol", actualFirElement)
is ConeKotlinType -> withConeTypeAttachment("coneType", actualFirElement)
null -> {}
else -> withAttachmentDetailed("element", actualFirElement) { it.toString() }
buildAttachment {
when (actualFirElement) {
is FirElement -> withFirEntry("firElement", actualFirElement)
is FirBasedSymbol<*> -> withFirSymbolEntry("firSymbol", actualFirElement)
is ConeKotlinType -> withConeTypeEntry("coneType", actualFirElement)
null -> {}
else -> withEntry("element", actualFirElement) { it.toString() }
}
}
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.api
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.createEmptySession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.BodyBuildingMode
@@ -133,7 +133,7 @@ object KtDeclarationAndFirDeclarationEqualityChecker {
}
}
}
else -> firErrorWithAttachment("Invalid type reference", fir = this)
else -> errorWithFirSpecificEntries("Invalid type reference", fir = this)
}
return if (isVararg) {
rendered.asArrayType()
@@ -166,7 +166,7 @@ object KtDeclarationAndFirDeclarationEqualityChecker {
}
append(typeRef.renderTypeAsKotlinType())
}
else -> firErrorWithAttachment("Invalid type reference", fir = this)
else -> errorWithFirSpecificEntries("Invalid type reference", fir = this)
}
private fun isTheSameTypes(
@@ -201,7 +201,7 @@ object KtDeclarationAndFirDeclarationEqualityChecker {
// Can be present as return type
"${lowerBound.renderTypeAsKotlinType()}..${upperBound.renderTypeAsKotlinType()}"
}
else -> firErrorWithAttachment("Type should not be present in Kotlin declaration", coneType = this)
else -> errorWithFirSpecificEntries("Type should not be present in Kotlin declaration", coneType = this)
}.replace('/', '.')
return rendered + nullability.suffix
}
@@ -19,10 +19,9 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirResolvableSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.firErrorWithAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.analysis.utils.errors.withPsiAttachment
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
@@ -40,7 +39,8 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.*
object LowLevelFirApiFacadeForResolveOnAir {
@@ -91,9 +91,9 @@ object LowLevelFirApiFacadeForResolveOnAir {
}
declaration.accept(expressionLocator)
return expressionLocator.result ?: firErrorWithAttachment("Resolved on-air element was not found in containing declaration") {
withPsiAttachment("place", place)
withPsiAttachment("elementToResolve", elementToResolve)
return expressionLocator.result ?: errorWithFirSpecificEntries("Resolved on-air element was not found in containing declaration") {
withPsiEntry("place", place)
withPsiEntry("elementToResolve", elementToResolve)
}
}
@@ -159,9 +159,9 @@ object LowLevelFirApiFacadeForResolveOnAir {
val sameDeclarationInOriginalFile = PsiTreeUtil.findSameElementInCopy(dependencyNonLocalDeclaration, originalKtFile)
?: firErrorWithAttachment("Cannot find original function matching") {
withPsiAttachment("matchingPsi", dependencyNonLocalDeclaration)
withPsiAttachment("originalFile", originalKtFile)
?: buildErrorWithAttachment("Cannot find original function matching") {
withPsiEntry("matchingPsi", dependencyNonLocalDeclaration)
withPsiEntry("originalFile", originalKtFile)
}
recordOriginalDeclaration(
@@ -194,8 +194,8 @@ object LowLevelFirApiFacadeForResolveOnAir {
replacement = replacement
)
val llFirResolvableSession = firFile.llFirResolvableSession
?: errorWithAttachment("FirFile session expected to be a resolvable session but was ${firFile.llFirSession::class.java}") {
withAttachment("firSession", firFile.llFirSession)
?: buildErrorWithAttachment("FirFile session expected to be a resolvable session but was ${firFile.llFirSession::class.java}") {
withEntry("firSession", firFile.llFirSession) { it.toString() }
}
val declarationResolver = llFirResolvableSession.moduleComponents.lazyFirDeclarationsResolver
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirFirProv
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LazyTransformerFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirAttachment
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.utils.errors.shouldIjPlatformExceptionBeRethrown
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
@@ -33,8 +33,8 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataCo
import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.utils.withAttachmentDetailed
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.*
internal class FirLazyDeclarationResolver(val moduleComponents: LLFirModuleResolveComponents) {
/**
@@ -430,7 +430,7 @@ private fun rethrowWithDetails(
toPhase: FirResolvePhase?
): Nothing {
if (shouldIjPlatformExceptionBeRethrown(e)) throw e
errorWithAttachment(
buildErrorWithAttachment(
buildString {
val moduleData = firDeclarationToResolve.llFirModuleData
appendLine("Error while resolving ${firDeclarationToResolve::class.java.name} ")
@@ -444,10 +444,10 @@ private fun rethrowWithDetails(
},
cause = e,
) {
withAttachmentDetailed("KtModule", firDeclarationToResolve.llFirModuleData.ktModule) { it.moduleDescription }
withAttachmentDetailed("session", firDeclarationToResolve.llFirSession) { it.toString() }
withAttachmentDetailed("moduleData", firDeclarationToResolve.moduleData) { it.toString() }
withFirAttachment("firDeclarationToResolve", firDeclarationToResolve)
withEntry("KtModule", firDeclarationToResolve.llFirModuleData.ktModule) { it.moduleDescription }
withEntry("session", firDeclarationToResolve.llFirSession) { it.toString() }
withEntry("moduleData", firDeclarationToResolve.moduleData) { it.toString() }
withFirEntry("firDeclarationToResolve", firDeclarationToResolve)
}
}
@@ -7,11 +7,10 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassOwner
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiTypeParameter
import com.intellij.psi.impl.compiled.ClsElementImpl
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
import org.jetbrains.kotlin.analysis.utils.errors.withPsiAttachment
import org.jetbrains.kotlin.analysis.utils.errors.*
import org.jetbrains.kotlin.asJava.KtLightClassMarker
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
@@ -22,9 +21,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.checkWithAttachment
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.utils.withAttachmentBuilder
class LLFirFirClassByPsiClassProvider(private val session: LLFirSession) : FirSessionComponent {
fun getFirClass(psiClass: PsiClass): FirRegularClassSymbol? {
@@ -36,16 +32,13 @@ class LLFirFirClassByPsiClassProvider(private val session: LLFirSession) : FirSe
"${LLFirFirClassByPsiClassProvider::class.simpleName} can create only non-kotlin classes"
}
checkWithAttachment(
checkWithAttachmentBuilder(
psiClass !is ClsElementImpl || !psiClass.hasAnnotation(JvmAnnotationNames.METADATA_FQ_NAME.asString()), {
"${LLFirFirClassByPsiClassProvider::class.simpleName} can create only non-kotlin classes, but got ${psiClass::class} with ${JvmAnnotationNames.METADATA_FQ_NAME.asString()} annotation"
}
) {
it.withAttachmentBuilder("psiClass") {
appendLine("file: ${psiClass.containingFile?.virtualFile?.path}")
appendLine("PsiClass:")
appendLine(psiClass.text)
}
withEntry("virtualFilePath", psiClass.containingFile.virtualFile?.path)
withPsiEntry("psiClass", psiClass)
}
if (psiClass.qualifiedName == null) {
@@ -53,18 +46,21 @@ class LLFirFirClassByPsiClassProvider(private val session: LLFirSession) : FirSe
}
val firClassSymbol = createFirClassFromFirProvider(psiClass)
checkWithAttachment(
firClassSymbol.fir.psi == psiClass,
val gotPsi = firClassSymbol.fir.psi
checkWithAttachmentBuilder(
gotPsi == psiClass,
{ "resulted FirClass.psi != requested PsiClass" }
) {
it.withAttachmentBuilder("info") {
appendLine("Requested ${psiClass::class.java.name}:")
appendLine("path: ${psiClass.containingFile?.virtualFile?.path}")
appendLine("modificationStamp: ${psiClass.containingFile.modificationStamp}")
appendLine()
appendLine("Got ${firClassSymbol.fir.psi!!::class.java.name}")
appendLine("path: ${firClassSymbol.fir.psi?.containingFile?.virtualFile?.path}")
appendLine("modificationStamp: ${firClassSymbol.fir.psi?.containingFile?.modificationStamp}")
withEntryGroup("Requested") {
withClassEntry("psiElementClass", psiClass)
withEntry("path", psiClass.containingFile?.virtualFile?.path)
withEntry("modificationStamp", psiClass.containingFile.modificationStamp.toString())
}
withEntryGroup("Got") {
withClassEntry("psiElementClass", gotPsi)
withEntry("path", gotPsi?.containingFile?.virtualFile?.path)
withEntry("modificationStamp", gotPsi?.containingFile?.modificationStamp.toString())
}
}
return firClassSymbol
@@ -75,9 +71,9 @@ class LLFirFirClassByPsiClassProvider(private val session: LLFirSession) : FirSe
?: error("No classId for non-local class")
val provider = session.nullableJavaSymbolProvider ?: session.symbolProvider
val symbol = provider.getClassLikeSymbolByClassId(classId)
?: errorWithAttachment("No classifier found") {
withPsiAttachment("psiClass", psiClass)
withAttachment("classId", classId.asString())
?: buildErrorWithAttachment("No classifier found") {
withPsiEntry("psiClass", psiClass)
withEntry("classId", classId) { it.asString() }
}
return symbol as FirRegularClassSymbol
}
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
import org.jetbrains.kotlin.analysis.utils.errors.withPsiAttachment
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
@@ -35,8 +34,8 @@ import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.utils.withAttachmentDetailed
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.*
internal abstract class LLFirResolvableResolveSession(
private val sessionProvider: LLFirSessionProvider,
@@ -103,9 +102,9 @@ internal abstract class LLFirResolvableResolveSession(
"Declaration should be resolvable module, instead it had ${module::class}"
}
val nonLocalNamedDeclaration = ktDeclaration.getNonLocalContainingOrThisDeclaration()
?: errorWithAttachment("Declaration should have non-local container") {
withPsiAttachment("ktDeclaration", ktDeclaration)
withAttachmentDetailed("module", module) { it.moduleDescription }
?: buildErrorWithAttachment("Declaration should have non-local container") {
withPsiEntry("ktDeclaration", ktDeclaration)
withEntry("module", module) { it.moduleDescription }
}
if (ktDeclaration == nonLocalNamedDeclaration) {
@@ -7,7 +7,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.KtDeclarationAndFirDeclarationEqualityChecker
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.analysis.utils.errors.ExceptionAttachmentBuilder
import org.jetbrains.kotlin.analysis.utils.errors.withClassEntry
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredConstructors
@@ -19,8 +20,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.withAttachmentBuilder
/**
* Allows to search for FIR declarations by compiled [KtDeclaration]s.
@@ -34,17 +33,17 @@ internal class FirDeclarationForCompiledElementSearcher(private val symbolProvid
is KtNamedFunction -> findNonLocalFunction(ktDeclaration)
is KtProperty -> findNonLocalProperty(ktDeclaration)
else -> firErrorWithAttachment("Unsupported compiled declaration of type", psi = ktDeclaration)
else -> errorWithFirSpecificEntries("Unsupported compiled declaration of type", psi = ktDeclaration)
}
}
private fun findNonLocalEnumEntry(declaration: KtEnumEntry): FirEnumEntry {
require(!declaration.isLocal)
val classId = declaration.containingClassOrObject?.getClassId()
?: firErrorWithAttachment("Non-local class should have classId", psi = declaration)
?: errorWithFirSpecificEntries("Non-local class should have classId", psi = declaration)
val classCandidate = symbolProvider.getClassLikeSymbolByClassId(classId)
?: firErrorWithAttachment("We should be able to find a symbol for $classId", psi = declaration)
?: errorWithFirSpecificEntries("We should be able to find a symbol for $classId", psi = declaration)
return (classCandidate.fir as? FirRegularClass)?.declarations?.first {
it is FirEnumEntry && it.name == declaration.nameAsName
@@ -53,11 +52,11 @@ internal class FirDeclarationForCompiledElementSearcher(private val symbolProvid
private fun findNonLocalClassLikeDeclaration(declaration: KtClassLikeDeclaration): FirClassLikeDeclaration {
val classId = declaration.getClassId()
?: firErrorWithAttachment("Non-local class should have classId", psi = declaration)
?: errorWithFirSpecificEntries("Non-local class should have classId", psi = declaration)
val classCandidate = symbolProvider.getClassLikeSymbolByClassId(classId)
?: firErrorWithAttachment("We should be able to find a symbol for $classId", psi = declaration) {
withAttachment("classId", classId.asString())
?: errorWithFirSpecificEntries("We should be able to find a symbol for $classId", psi = declaration) {
withEntry("classId", classId) { it.asString() }
}
return classCandidate.fir
@@ -65,16 +64,16 @@ internal class FirDeclarationForCompiledElementSearcher(private val symbolProvid
private fun findConstructorOfNonLocalClass(declaration: KtConstructor<*>): FirConstructor {
val containingClass = declaration.containingClassOrObject
?: firErrorWithAttachment("Constructor must have outer class", psi = declaration)
?: errorWithFirSpecificEntries("Constructor must have outer class", psi = declaration)
require(!containingClass.isLocal)
val classId = containingClass.getClassId()
?: firErrorWithAttachment("Non-local class should have classId", psi = declaration)
?: errorWithFirSpecificEntries("Non-local class should have classId", psi = declaration)
val constructorCandidate =
symbolProvider.getClassDeclaredConstructors(classId)
.singleOrNull { representSameConstructor(declaration, it.fir) }
?: firErrorWithAttachment("We should be able to find a constructor", psi = declaration)
?: errorWithFirSpecificEntries("We should be able to find a constructor", psi = declaration)
return constructorCandidate.fir
}
@@ -86,7 +85,7 @@ internal class FirDeclarationForCompiledElementSearcher(private val symbolProvid
val functionCandidate =
candidates
.singleOrNull { KtDeclarationAndFirDeclarationEqualityChecker.representsTheSameDeclaration(declaration, it.fir) }
?: firErrorWithAttachment("We should be able to find a symbol for function", psi = declaration) {
?: errorWithFirSpecificEntries("We should be able to find a symbol for function", psi = declaration) {
withCandidates(candidates)
}
@@ -100,7 +99,7 @@ internal class FirDeclarationForCompiledElementSearcher(private val symbolProvid
val candidates = symbolProvider.findPropertyCandidates(declaration)
val propertyCandidate =
candidates.singleOrNull { KtDeclarationAndFirDeclarationEqualityChecker.representsTheSameDeclaration(declaration, it.fir) }
?: firErrorWithAttachment("We should be able to find a symbol for property", psi = declaration) {
?: errorWithFirSpecificEntries("We should be able to find a symbol for property", psi = declaration) {
withCandidates(candidates)
}
@@ -124,7 +123,7 @@ private fun FirSymbolProvider.findCallableCandidates(
}
val containerClassId = declaration.containingClassOrObject?.getClassId()
?: firErrorWithAttachment("No containing non-local declaration found for", psi = declaration)
?: errorWithFirSpecificEntries("No containing non-local declaration found for", psi = declaration)
return getClassDeclaredFunctionSymbols(containerClassId, declaration.nameAsSafeName) +
getClassDeclaredPropertySymbols(containerClassId, declaration.nameAsSafeName)
@@ -138,16 +137,16 @@ private fun representSameConstructor(psiConstructor: KtConstructor<*>, firConstr
return KtDeclarationAndFirDeclarationEqualityChecker.representsTheSameDeclaration(psiConstructor, firConstructor)
}
private fun KotlinExceptionWithAttachments.withCandidates(candidates: List<FirBasedSymbol<*>>) {
withAttachmentBuilder("candidates") {
appendLine("Candidates count ${candidates.size}")
for ((index, candidate) in candidates.withIndex()) {
appendLine("Candidate $index, ${candidate::class.java}")
val ktModule = candidate.llFirModuleData.ktModule
appendLine("From ${ktModule::class.java} ${ktModule.moduleDescription}")
appendLine("Origin ${candidate.origin}")
appendLine(debugFirRenderer.renderElementAsString(candidate.fir))
appendLine()
private fun ExceptionAttachmentBuilder.withCandidates(candidates: List<FirBasedSymbol<*>>) {
withEntry("Candidates count", candidates.size.toString())
for ((index, candidate) in candidates.withIndex()) {
val ktModule = candidate.llFirModuleData.ktModule
withEntryGroup(index.toString()) {
withClassEntry("candidateClass", candidate)
withEntry("module", ktModule) { it.moduleDescription }
withEntry("origin", candidate.origin.toString())
withFirEntry("candidateFir", candidate.fir)
}
}
}
@@ -17,6 +17,6 @@ fun FirDeclaration.getContainingFile(): FirFile? {
is FirFile -> this
is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol)
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(symbol)
else -> firErrorWithAttachment("Unsupported declaration ${this::class.java}", fir = this)
else -> errorWithFirSpecificEntries("Unsupported declaration ${this::class.java}", fir = this)
}
}
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
@@ -30,7 +29,7 @@ internal fun KtDeclaration.findSourceNonLocalFirDeclaration(
//TODO test what way faster
findSourceNonLocalFirDeclarationByProvider(firFileBuilder, provider, containerFirFile)?.let { return it }
findSourceOfNonLocalFirDeclarationByTraversingWholeTree(firFileBuilder, containerFirFile)?.let { return it }
firErrorWithAttachment("No fir element was found for", psi = this)
errorWithFirSpecificEntries("No fir element was found for", psi = this)
}
internal fun KtDeclaration.findFirDeclarationForAnyFirSourceDeclaration(
@@ -45,7 +44,7 @@ internal fun KtDeclaration.findFirDeclarationForAnyFirSourceDeclaration(
firDeclaration.psi == this || firDeclaration.psi == originalDeclaration
}
return fir
?: firErrorWithAttachment("FirDeclaration was not found", psi = this)
?: errorWithFirSpecificEntries("FirDeclaration was not found", psi = this)
}
internal inline fun <reified F : FirDeclaration> KtDeclaration.findFirDeclarationForAnyFirSourceDeclarationOfType(
@@ -95,12 +94,12 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
}
this is KtConstructor<*> -> {
val containingClass = containingClassOrObject
?: firErrorWithAttachment("Container class should be not null for KtConstructor", psi = this)
?: errorWithFirSpecificEntries("Container class should be not null for KtConstructor", psi = this)
val containerClassFir = containingClass.findFir(provider) as? FirRegularClass ?: return null
containerClassFir.declarations.firstOrNull { it.psi === this }
}
this is KtTypeAlias -> findFir(provider)
else -> firErrorWithAttachment("Invalid container", psi = this)
else -> errorWithFirSpecificEntries("Invalid container", psi = this)
}
return candidate?.takeIf { it.realPsi == this }
}
@@ -6,8 +6,9 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.utils.errors.withPsiAttachment
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.analysis.utils.errors.ExceptionAttachmentBuilder
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.renderer.ConeTypeRendererForDebugging
@@ -16,58 +17,49 @@ import org.jetbrains.kotlin.fir.renderer.FirRenderer
import org.jetbrains.kotlin.fir.renderer.FirResolvePhaseRenderer
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.errorWithAttachment
import org.jetbrains.kotlin.utils.withAttachmentDetailed
fun KotlinExceptionWithAttachments.withFirAttachment(name: String, fir: FirElement): KotlinExceptionWithAttachments {
withAttachmentDetailed(name, fir, debugFirRenderer::renderElementAsString)
withPsiAttachment("${name}Psi", fir.psi)
return this
fun ExceptionAttachmentBuilder.withFirEntry(name: String, fir: FirElement) {
withEntry(name, fir) {
FirRenderer(
resolvePhaseRenderer = FirResolvePhaseRenderer(),
declarationRenderer = FirDeclarationRendererWithAttributes()
).renderElementAsString(it)
}
withPsiEntry("${name}Psi", fir.psi)
}
fun KotlinExceptionWithAttachments.withFirSymbolAttachment(name: String, symbol: FirBasedSymbol<*>): KotlinExceptionWithAttachments {
withAttachment("${name}Class", symbol::class.java.name)
withFirAttachment("${name}Fir", symbol.fir)
return this
fun ExceptionAttachmentBuilder.withFirSymbolEntry(name: String, symbol: FirBasedSymbol<*>) {
withFirEntry("${name}Fir", symbol.fir)
}
fun KotlinExceptionWithAttachments.withConeTypeAttachment(name: String, coneType: ConeKotlinType): KotlinExceptionWithAttachments {
withAttachmentDetailed(name, coneType) {
fun ExceptionAttachmentBuilder.withConeTypeEntry(name: String, coneType: ConeKotlinType) {
withEntry(name, coneType) {
buildString { ConeTypeRendererForDebugging(this).render(it) }
}
return this
}
fun firErrorWithAttachment(
fun errorWithFirSpecificEntries(
message: String,
cause: Throwable? = null,
fir: FirElement? = null,
coneType: ConeKotlinType? = null,
psi: PsiElement? = null,
attachments: KotlinExceptionWithAttachments.() -> Unit = {}
additionalInfos: ExceptionAttachmentBuilder.() -> Unit = {}
): Nothing {
errorWithAttachment(message, cause) {
buildErrorWithAttachment(message, cause) {
if (fir != null) {
withFirAttachment("fir", fir)
withFirEntry("fir", fir)
}
if (psi != null) {
withPsiAttachment("psi", psi)
withPsiEntry("psi", psi)
}
if (coneType != null) {
withConeTypeAttachment("coneType", coneType)
withConeTypeEntry("coneType", coneType)
}
attachments ()
additionalInfos()
}
}
val debugFirRenderer =
FirRenderer(resolvePhaseRenderer = FirResolvePhaseRenderer(), declarationRenderer = FirDeclarationRendererWithAttributes())
@@ -7,12 +7,10 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import com.intellij.openapi.progress.ProgressManager
import com.intellij.psi.util.*
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
import java.util.concurrent.TimeUnit
@@ -54,11 +52,11 @@ internal val FirElement.isErrorElement
internal val FirDeclaration.ktDeclaration: KtDeclaration
get() {
val psi = psi
?: firErrorWithAttachment("PSI element was not found", fir = this)
?: errorWithFirSpecificEntries("PSI element was not found", fir = this)
return when (psi) {
is KtDeclaration -> psi
is KtObjectLiteralExpression -> psi.objectDeclaration
else -> firErrorWithAttachment(
else -> errorWithFirSpecificEntries(
"FirDeclaration.psi (${this::class.simpleName}) should be KtDeclaration but was ${psi::class.simpleName}",
fir = this,
psi = psi,
@@ -41,23 +41,6 @@ open class KotlinExceptionWithAttachments : RuntimeException, ExceptionWithAttac
}
fun KotlinExceptionWithAttachments.withAttachmentBuilder(
name: String,
buildContent: StringBuilder.() -> Unit
): KotlinExceptionWithAttachments {
return withAttachment(name, buildString { buildContent() })
}
fun <T> KotlinExceptionWithAttachments.withAttachmentDetailed(
name: String,
content: T?,
render: (T) -> String
): KotlinExceptionWithAttachments {
withAttachment("${name}Class", content?.let { it::class.java.name })
withAttachment(name, content?.let(render))
return this
}
@OptIn(ExperimentalContracts::class)
inline fun checkWithAttachment(value: Boolean, lazyMessage: () -> String, attachments: (KotlinExceptionWithAttachments) -> Unit = {}) {
contract { returns() implies (value) }
@@ -68,14 +51,3 @@ inline fun checkWithAttachment(value: Boolean, lazyMessage: () -> String, attach
throw e
}
}
inline fun errorWithAttachment(
message: String,
cause: Throwable? = null,
attachments: KotlinExceptionWithAttachments.() -> Unit = {}
): Nothing {
val exception = KotlinExceptionWithAttachments(message, cause)
attachments(exception)
throw exception
}