Rework checkWithAttachment/requireWithAttachment

* better naming
* throw corresponding KotlinIllegalStateExceptionWithAttachments/KotlinIllegalArgumentExceptionWithAttachments instead of general KotlinRuntimeExceptionWithAttachments
This commit is contained in:
Ilya Kirillov
2023-06-30 15:56:26 +02:00
committed by Space Team
parent 2d791eb292
commit 4b3bff3344
12 changed files with 40 additions and 34 deletions
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.bas
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
import org.jetbrains.kotlin.analysis.api.symbols.psiSafe
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
@@ -33,7 +33,7 @@ internal class KtFe10MultiplatformInfoProvider(
val expectsForActual = (expectedCompatibilityMap[ExpectActualCompatibility.Compatible]
?: expectedCompatibilityMap.values.flatten())
check(expectsForActual.size <= 1) { "expected as maximum one `expect` for the actual" }
checkWithAttachmentBuilder(expectsForActual.size <= 1, message = { "expected as maximum one `expect` for the actual" }) {
checkWithAttachment(expectsForActual.size <= 1, message = { "expected as maximum one `expect` for the actual" }) {
withEntry("actual", memberDescriptor.toString())
withEntry("expectsForActualSize", expectsForActual.size.toString())
for ((index, expectForActual) in expectsForActual.withIndex()) {
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationApplication
import org.jetbrains.kotlin.analysis.api.fir.toKtAnnotationInfo
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withClassEntry
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
@@ -47,7 +47,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
internal fun mapAnnotationParameters(annotation: FirAnnotation): Map<Name, FirExpression> {
if (annotation is FirAnnotationCall && annotation.arguments.isEmpty()) return emptyMap()
checkWithAttachmentBuilder(annotation.resolved, { "By now the annotations argument mapping should have been resolved" }) {
checkWithAttachment(annotation.resolved, { "By now the annotations argument mapping should have been resolved" }) {
withFirEntry("annotation", annotation)
withClassEntry("annotationTypeRef", annotation.annotationTypeRef)
withClassEntry("typeRef", annotation.typeRef)
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolEntry
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus
import org.jetbrains.kotlin.fir.declarations.expectForActual
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -29,7 +29,7 @@ internal class KtFirMultiplatformInfoProvider(
if (!isActual(actual)) return null
val expectsForActual = firSymbol.expectForActual?.get(ExpectActualCompatibility.Compatible) ?: return null
checkWithAttachmentBuilder(expectsForActual.size <= 1, message = { "expected as maximum one `expect` for the actual" }) {
checkWithAttachment(expectsForActual.size <= 1, message = { "expected as maximum one `expect` for the actual" }) {
withFirSymbolEntry("actual", firSymbol)
withEntry("expectsForActualSize", expectsForActual.size.toString())
for ((index, expectForActual) in expectsForActual.withIndex()) {
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtClassTypeQualifier
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignation
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.fir.containingClassForLocal
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isInner
@@ -94,7 +94,7 @@ internal object UsualClassTypeQualifierBuilder {
}
private fun collectDesignationPathForLocal(declaration: FirClassLikeDeclaration): List<FirDeclaration> {
checkWithAttachmentBuilder(
checkWithAttachment(
declaration.isLocal,
message = { "${declaration::class} is not local" }
) {
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingClass
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getContainingFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
import org.jetbrains.kotlin.builtins.StandardNames
@@ -151,7 +151,7 @@ private fun collectDesignationPathWithContainingClass(target: FirDeclaration, co
?: findKotlinStdlibClass(classId, target)
}
checkWithAttachmentBuilder(
checkWithAttachment(
declaration is FirRegularClass,
message = { "'FirRegularClass' expected as a containing declaration, got '${declaration?.javaClass?.name}'" },
buildAttachment = {
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.ThreadSafe
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.fir.builder.BodyBuildingMode
import org.jetbrains.kotlin.fir.builder.PsiRawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirFile
@@ -25,7 +25,7 @@ internal class LLFirFileBuilder(val moduleComponents: LLFirModuleResolveComponen
val contextualModule = moduleComponents.module
val actualFileModule = projectStructureProvider.getModule(ktFile, contextualModule)
checkWithAttachmentBuilder(actualFileModule == contextualModule, { "Modules are inconsistent" }) {
checkWithAttachment(actualFileModule == contextualModule, { "Modules are inconsistent" }) {
withEntry("file", ktFile.name)
withEntry("file module", actualFileModule) {
it.toString()
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.analysis.utils.classIdIfNonLocal
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
class LLFirFirClassByPsiClassProvider(private val session: LLFirSession) : FirSessionComponent {
fun getFirClass(psiClass: PsiClass): FirRegularClassSymbol? {
@@ -32,7 +32,7 @@ class LLFirFirClassByPsiClassProvider(private val session: LLFirSession) : FirSe
"${LLFirFirClassByPsiClassProvider::class.simpleName} can create only non-kotlin classes"
}
checkWithAttachmentBuilder(
checkWithAttachment(
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"
}
@@ -47,7 +47,7 @@ class LLFirFirClassByPsiClassProvider(private val session: LLFirSession) : FirSe
val firClassSymbol = createFirClassFromFirProvider(psiClass)
val gotPsi = firClassSymbol.fir.psi
checkWithAttachmentBuilder(
checkWithAttachment(
gotPsi == psiClass,
{ "resulted FirClass.psi != requested PsiClass" }
) {
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockPro
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDelegatedConstructorIsResolved
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.*
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.fir.FirElementWithResolveState
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
import org.jetbrains.kotlin.fir.FirSession
@@ -103,7 +103,7 @@ private class LLFirBodyTargetResolver(
}
private fun calculateControlFlowGraph(target: FirRegularClass) {
checkWithAttachmentBuilder(
checkWithAttachment(
target.controlFlowGraphReference == null,
{ "'controlFlowGraphReference' should be 'null' if the class phase < $resolverPhase)" },
) {
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.utils.exceptions.requireWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.packageFqName
@@ -70,11 +70,11 @@ internal object FirElementFinder {
expectedDeclarationAcceptor: (FirDeclaration) -> Boolean,
): FirDeclarationDesignation? {
if (containerClassId != null) {
requireWithAttachmentBuilder(!containerClassId.isLocal, { "ClassId should not be local" }) {
requireWithAttachment(!containerClassId.isLocal, { "ClassId should not be local" }) {
withEntry("classId", containerClassId) { it.asString() }
}
requireWithAttachmentBuilder(
requireWithAttachment(
firFile.packageFqName == containerClassId.packageFqName,
{ "ClassId should not be local" }
) {
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.utils.exceptions.ExceptionAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirElementWithResolveState
import org.jetbrains.kotlin.fir.contracts.FirLegacyRawContractDescription
@@ -30,7 +30,7 @@ internal inline fun checkTypeRefIsResolved(
acceptImplicitTypeRef: Boolean = false,
extraAttachment: ExceptionAttachmentBuilder.() -> Unit = {},
) {
checkWithAttachmentBuilder(
checkWithAttachment(
condition = typeRef is FirResolvedTypeRef || acceptImplicitTypeRef && typeRef is FirImplicitTypeRef,
message = {
buildString {
@@ -66,7 +66,7 @@ internal fun checkBodyIsResolved(function: FirFunction) {
internal fun checkExpectForActualIsResolved(memberDeclaration: FirMemberDeclaration) {
if (!memberDeclaration.isActual) return
checkWithAttachmentBuilder(
checkWithAttachment(
condition = memberDeclaration.expectForActual != null,
message = { "Expect for actual matching is missing" }
) {
@@ -87,7 +87,7 @@ internal fun checkReferenceIsResolved(
owner: FirResolvable,
extraAttachment: ExceptionAttachmentBuilder.() -> Unit = {},
) {
checkWithAttachmentBuilder(
checkWithAttachment(
condition = reference is FirResolvedNamedReference || reference is FirErrorNamedReference || reference is FirFromMissingDependenciesNamedReference,
message = {
"Expected ${FirNamedReference::class.simpleName}, " +
@@ -116,7 +116,7 @@ internal fun checkDefaultValueIsResolved(parameter: FirValueParameter) {
}
internal fun checkDeprecationProviderIsResolved(declaration: FirDeclaration, provider: DeprecationsProvider) {
checkWithAttachmentBuilder(
checkWithAttachment(
condition = provider !is UnresolvedDeprecationProvider,
message = { "Unresolved deprecation provider found for ${declaration::class.simpleName}" }
) {
@@ -136,7 +136,7 @@ internal fun checkReceiverTypeRefIsResolved(declaration: FirCallableDeclaration,
internal fun checkContractDescriptionIsResolved(declaration: FirContractDescriptionOwner) {
val contractDescription = declaration.contractDescription
checkWithAttachmentBuilder(
checkWithAttachment(
condition = contractDescription is FirResolvedContractDescription ||
contractDescription is FirEmptyContractDescription ||
contractDescription is FirLegacyRawContractDescription /* TODO: should be dropped after KT-60310 */,
@@ -148,7 +148,7 @@ internal fun checkContractDescriptionIsResolved(declaration: FirContractDescript
internal fun checkDeclarationStatusIsResolved(declaration: FirMemberDeclaration) {
val status = declaration.status
checkWithAttachmentBuilder(
checkWithAttachment(
condition = status is FirResolvedDeclarationStatus,
message = { "Expected ${FirResolvedDeclarationStatus::class.simpleName} but ${status::class.simpleName} found for ${declaration::class.simpleName}" }
) {
@@ -161,7 +161,7 @@ internal fun <T> checkAnnotationArgumentsMappingIsResolved(
) where T : FirAnnotationContainer, T : FirElementWithResolveState {
for (annotation in annotationContainer.annotations) {
if (annotation is FirAnnotationCall) {
checkWithAttachmentBuilder(
checkWithAttachment(
condition = annotation.argumentList is FirResolvedArgumentList,
message = {
buildString {
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignation
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachmentBuilder
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.fir.FirElementWithResolveState
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.resolvePhase
internal fun FirElementWithResolveState.checkPhase(requiredResolvePhase: FirResolvePhase) {
@OptIn(ResolveStateAccess::class)
val declarationResolveState = resolveState
checkWithAttachmentBuilder(
checkWithAttachment(
declarationResolveState.resolvePhase >= requiredResolvePhase,
{ "At least $requiredResolvePhase expected but $declarationResolveState found for ${this::class.simpleName}" },
) {
@@ -91,27 +91,33 @@ inline fun rethrowExceptionWithDetails(
@OptIn(ExperimentalContracts::class)
inline fun checkWithAttachmentBuilder(
inline fun checkWithAttachment(
condition: Boolean,
message: () -> String,
attachmentName: String = "info.txt",
buildAttachment: ExceptionAttachmentBuilder.() -> Unit = {},
) {
contract { returns() implies (condition) }
if (!condition) {
errorWithAttachment(message(), buildAttachment = buildAttachment)
val exception = KotlinIllegalStateExceptionWithAttachments(message())
exception.buildAttachment(attachmentName) { buildAttachment() }
throw exception
}
}
@OptIn(ExperimentalContracts::class)
inline fun requireWithAttachmentBuilder(
inline fun requireWithAttachment(
condition: Boolean,
message: () -> String,
attachmentName: String = "info.txt",
buildAttachment: ExceptionAttachmentBuilder.() -> Unit = {},
) {
contract { returns() implies (condition) }
if (!condition) {
errorWithAttachment(message(), buildAttachment = buildAttachment)
val exception = KotlinIllegalArgumentExceptionWithAttachments(message())
exception.buildAttachment(attachmentName) { buildAttachment() }
throw exception
}
}