[Analysis API FIR, LL FIR] use exceptionWithAttachment to not leak user data

This commit is contained in:
Ilya Kirillov
2022-07-23 15:59:30 +02:00
parent b701c1c6f6
commit 827c262f68
25 changed files with 351 additions and 79 deletions
@@ -9,13 +9,16 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.analysis.api.fir.utils.withSymbolAttachment
import org.jetbrains.kotlin.analysis.api.impl.base.CachingKtAnalysisSessionProvider
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
@OptIn(KtAnalysisApiInternals::class)
class KtFirAnalysisSessionProvider(project: Project) : CachingKtAnalysisSessionProvider<LLFirResolveSession>(project) {
@@ -26,7 +29,9 @@ class KtFirAnalysisSessionProvider(project: Project) : CachingKtAnalysisSessionP
override fun getFirResolveSession(contextSymbol: KtSymbol): LLFirResolveSession {
return when (contextSymbol) {
is KtFirSymbol<*> -> contextSymbol.firResolveSession
else -> error("Invalid symbol ${contextSymbol::class}")
else -> errorWithAttachment("Invalid symbol") {
withSymbolAttachment("symbol", contextSymbol)
}
}
}
@@ -20,6 +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.providers.createPackageProvider
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import org.jetbrains.kotlin.fir.*
@@ -49,6 +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 kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
@@ -203,7 +208,10 @@ internal class KtSymbolByFirBuilder constructor(
return buildFunctionSymbol(it.symbol)
}
if (firSymbol.dispatchReceiverType?.contains { it is ConeStubType } == true) {
return buildFunctionSymbol(firSymbol.originalIfFakeOverride() ?: error("Stub type in real declaration"))
return buildFunctionSymbol(
firSymbol.originalIfFakeOverride()
?: firErrorWithAttachment("Stub type in real declaration", fir = firSymbol.fir)
)
}
check(firSymbol.origin != FirDeclarationOrigin.SamConstructor)
@@ -579,8 +587,22 @@ internal class KtSymbolByFirBuilder constructor(
}
companion object {
private fun throwUnexpectedElementError(element: Any): Nothing {
error("Unexpected ${element::class.simpleName}")
private fun throwUnexpectedElementError(element: FirBasedSymbol<*>): Nothing {
errorWithAttachment("Unexpected ${element::class.simpleName}") {
withFirSymbolAttachment("firSymbol", element)
}
}
private fun throwUnexpectedElementError(element: FirElement): Nothing {
errorWithAttachment("Unexpected ${element::class.simpleName}") {
withFirAttachment("firElement", element)
}
}
private fun throwUnexpectedElementError(element: ConeKotlinType): Nothing {
errorWithAttachment("Unexpected ${element::class.simpleName}") {
withConeTypeAttachment("coneType", element)
}
}
@OptIn(ExperimentalContracts::class)
@@ -25,6 +25,7 @@ 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.utils.printer.parentOfType
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
@@ -151,7 +152,7 @@ internal class KtFirCallResolver(
when (val calleeReference = calleeReference) {
is FirResolvedNamedReference -> {
val call = createKtCall(psi, this, null, resolveFragmentOfCall)
?: error("expect `createKtCall` to succeed for resolvable case")
?: firErrorWithAttachment("expect `createKtCall` to succeed for resolvable case", fir = this, psi = psi)
KtSuccessCallInfo(call)
}
is FirErrorNamedReference -> {
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirReceiverParameterSymbo
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirTypeParameterSymbol
import org.jetbrains.kotlin.analysis.api.fir.utils.getContainingKtModule
import org.jetbrains.kotlin.analysis.api.fir.utils.withSymbolAttachment
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
@@ -22,6 +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
internal class KtFirSymbolContainingDeclarationProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -85,21 +87,33 @@ internal class KtFirSymbolContainingDeclarationProvider(
private fun getContainingPsi(symbol: KtFirSymbol<*>): KtDeclaration {
val source = symbol.firSymbol.source
val thisSource = when (source?.kind) {
null -> error("PSI should present for declaration built by Kotlin code")
null -> errorWithAttachment("PSI should present for declaration built by Kotlin code") {
withSymbolAttachment("symbolForContainingPsi", symbol)
}
KtFakeSourceElementKind.ImplicitConstructor ->
return source.psi as KtDeclaration
KtFakeSourceElementKind.PropertyFromParameter -> return source.psi?.parentOfType<KtPrimaryConstructor>()!!
KtFakeSourceElementKind.DefaultAccessor -> return source.psi as KtProperty
KtFakeSourceElementKind.ItLambdaParameter -> return source.psi as KtFunctionLiteral
KtRealSourceElementKind -> source.psi!!
else -> error("Unexpected FirSourceElement: kind=${source.kind} element=${source.psi!!::class.simpleName}")
else ->
errorWithAttachment("errorWithAttachment FirSourceElement: kind=${source.kind} element=${source.psi!!::class.simpleName}") {
withSymbolAttachment("symbolForContainingPsi", symbol)
}
}
return when (symbol.origin) {
KtSymbolOrigin.SOURCE -> thisSource.getContainingKtDeclaration()
?: error("Containing declaration should present for non-toplevel declaration")
?: errorWithAttachment("Containing declaration should present for non-toplevel declaration") {
withSymbolAttachment("symbolForContainingPsi", symbol)
}
KtSymbolOrigin.SOURCE_MEMBER_GENERATED -> thisSource as KtDeclaration
else -> error("Unsupported declaration origin ${symbol.origin}")
else -> errorWithAttachment("Unsupported declaration origin ${symbol.origin}") {
withSymbolAttachment("symbolForContainingPsi", symbol)
}
}
}
@@ -113,21 +127,31 @@ internal class KtFirSymbolContainingDeclarationProvider(
require(symbol.origin == KtSymbolOrigin.LIBRARY || symbol.origin == KtSymbolOrigin.JAVA)
check(symbol.symbolKind == KtSymbolKind.CLASS_MEMBER)
fun error(message: String): Nothing {
errorWithAttachment(message) {
withSymbolAttachment("symbolToGetContaining", symbol)
}
}
val containingClassId = when (symbol) {
is KtClassLikeSymbol -> {
val classId = symbol.classIdIfNonLocal ?: error("classId should not be null for non-local declaration")
val classId = symbol.classIdIfNonLocal
?: error("classId should not be null for non-local declaration")
classId.outerClassId
}
is KtFunctionSymbol -> {
val fqName = symbol.callableIdIfNonLocal ?: error("callableIdIfNonLocal should not be null for non-local declaration")
val fqName = symbol.callableIdIfNonLocal
?: error("callableIdIfNonLocal should not be null for non-local declaration")
fqName.classId
}
is KtEnumEntrySymbol -> {
val classId = symbol.containingEnumClassIdIfNonLocal ?: error("fqName should not be null for non-local declaration")
val classId = symbol.containingEnumClassIdIfNonLocal
?: error("fqName should not be null for non-local declaration")
classId.outerClassId
}
is KtPropertySymbol -> {
val fqName = symbol.callableIdIfNonLocal ?: error("fqName should not be null for non-local declaration")
val fqName = symbol.callableIdIfNonLocal
?: error("fqName should not be null for non-local declaration")
fqName.classId
}
is KtConstructorSymbol -> {
@@ -137,6 +161,6 @@ internal class KtFirSymbolContainingDeclarationProvider(
else -> error("We should not have a ${symbol::class} from a library")
} ?: error("outerClassId should not be null for member declaration")
val containingClass = containingClassId.getCorrespondingToplevelClassOrObjectSymbol()
return containingClass ?: error("Class with id $containingClassId should exists")
return containingClass ?: error("Class by class id should exists")
}
}
@@ -11,17 +11,18 @@ 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.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
import org.jetbrains.kotlin.fir.originalIfFakeOverride
import org.jetbrains.kotlin.fir.render
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
internal interface KtFirSymbol<out S : FirBasedSymbol<*>> : KtSymbol, KtLifetimeOwner {
val firSymbol: S
@@ -49,6 +50,7 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori
else -> KtSymbolOrigin.SOURCE
}
}
FirDeclarationOrigin.Precompiled -> KtSymbolOrigin.SOURCE
FirDeclarationOrigin.Library, FirDeclarationOrigin.BuiltIns -> KtSymbolOrigin.LIBRARY
is FirDeclarationOrigin.Java -> KtSymbolOrigin.JAVA
@@ -60,26 +62,36 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori
when (this) {
is FirSyntheticProperty,
is FirSyntheticPropertyAccessor -> KtSymbolOrigin.JAVA_SYNTHETIC_PROPERTY
else -> throw InvalidFirDeclarationOriginForSymbol(this)
else -> errorWithAttachment("Invalid FirDeclarationOrigin ${origin::class.simpleName}") {
withFirAttachment("firToGetOrigin", this@ktSymbolOrigin)
}
}
}
FirDeclarationOrigin.ImportedFromObject -> {
val importedFromObjectData = (this as FirCallableDeclaration).importedFromObjectData
?: error("Declaration has ImportedFromObject origin, but no importedFromObjectData present")
?: errorWithAttachment("Declaration has ImportedFromObject origin, but no importedFromObjectData present") {
withFirAttachment("firToGetOrigin", this@ktSymbolOrigin)
}
importedFromObjectData.original.ktSymbolOrigin()
}
FirDeclarationOrigin.WrappedIntegerOperator -> {
val original = (this as FirSimpleFunction).originalForWrappedIntegerOperator?.fir
?: error("Declaration has WrappedIntegerOperator origin, but no originalForWrappedIntegerOperator present")
?: firErrorWithAttachment(
"Declaration has WrappedIntegerOperator origin, but no originalForWrappedIntegerOperator present",
fir = this
)
original.ktSymbolOrigin()
}
is FirDeclarationOrigin.Plugin -> KtSymbolOrigin.PLUGIN
FirDeclarationOrigin.RenamedForOverride -> KtSymbolOrigin.JAVA
FirDeclarationOrigin.SubstitutionOverride -> KtSymbolOrigin.SUBSTITUTION_OVERRIDE
FirDeclarationOrigin.DynamicScope -> throw InvalidFirDeclarationOriginForSymbol(this)
FirDeclarationOrigin.DynamicScope -> errorWithAttachment("Invalid FirDeclarationOrigin ${origin::class.simpleName}") {
withFirAttachment("firToGetOrigin", this@ktSymbolOrigin)
}
}
class InvalidFirDeclarationOriginForSymbol(declaration: FirDeclaration) :
IllegalStateException("Invalid FirDeclarationOrigin ${declaration.origin::class.simpleName} for ${declaration.render()}")
@@ -10,6 +10,9 @@ 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.low.level.api.fir.util.withPsiAttachment
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
import org.jetbrains.kotlin.fir.render
@@ -20,6 +23,7 @@ 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
internal class KtFirSymbolProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -28,8 +32,9 @@ internal class KtFirSymbolProvider(
override fun getParameterSymbol(psi: KtParameter): KtVariableLikeSymbol {
return when {
psi.isFunctionTypeParameter -> error(
"Creating KtValueParameterSymbol for function type parameter is not possible. Please see the KDoc of getParameterSymbol"
psi.isFunctionTypeParameter -> firErrorWithAttachment(
"Creating KtValueParameterSymbol for function type parameter is not possible. Please see the KDoc of getParameterSymbol",
psi = psi,
)
psi.isLoopParameter -> {
@@ -63,7 +68,10 @@ internal class KtFirSymbolProvider(
}
is FirAnonymousFunctionSymbol -> firSymbolBuilder.functionLikeBuilder.buildAnonymousFunctionSymbol(firSymbol)
else -> error("Unexpected ${firSymbol.fir.renderWithType()}")
else -> errorWithAttachment("Unexpected ${firSymbol::class}") {
withFirSymbolAttachment("firSymbol", firSymbol)
withPsiAttachment("function", psi)
}
}
}
@@ -117,7 +125,10 @@ internal class KtFirSymbolProvider(
val firClass =
when (val firClassLike = psi.resolveToFirSymbolOfType<FirClassLikeSymbol<*>>(firResolveSession)) {
is FirTypeAliasSymbol -> firClassLike.fullyExpandedClass(firResolveSession.useSiteFirSession)
?: error("${firClassLike.fir.render()} should be expanded to the expected type alias")
?: errorWithAttachment("${firClassLike.fir::class} should be expanded to the expected type alias") {
withFirSymbolAttachment("firClassLikeSymbol", firClassLike)
withPsiAttachment("ktClassOrObject", psi)
}
is FirAnonymousObjectSymbol -> firClassLike
is FirRegularClassSymbol -> firClassLike
}
@@ -17,6 +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.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
@@ -32,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)
?: error("Class ${coneType.lookupTag} was not found")
?: firErrorWithAttachment("Class was not found", coneType = coneType)
}
override val typeArguments: List<KtTypeArgument> by cached {
coneType.typeArguments.map { typeArgument ->
@@ -14,6 +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.fir.types.ConeTypeParameterType
import org.jetbrains.kotlin.fir.types.renderForDebugging
import org.jetbrains.kotlin.name.Name
@@ -26,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)
?: error("Type parameter ${coneType.lookupTag} was not found")
?: firErrorWithAttachment("Type parameter was not found", coneType = coneType)
}
override val annotationsList: KtAnnotationsList by cached {
@@ -15,6 +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.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.renderForDebugging
import org.jetbrains.kotlin.name.ClassId
@@ -27,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)
?: error("Class ${coneType.lookupTag} was not found")
?: firErrorWithAttachment("Class was not found", coneType = coneType)
}
override val typeArguments: List<KtTypeArgument> by cached {
coneType.typeArguments.map { typeArgument ->
@@ -0,0 +1,26 @@
/*
* 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.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.low.level.api.fir.util.withPsiAttachment
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)
if (symbol is KtFirSymbol<*>) {
val symbolFir = symbol.firSymbol.fir
withFirAttachment("${name}Fir", symbolFir)
}
return this
}