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