From 2e9f9f987bbe3f467a43f82944e1d781f5af098e Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Wed, 21 Sep 2022 15:08:52 +0300 Subject: [PATCH] [FIR] KT-44698: Print file:line:offset on K2 crash ^KT-44698 Fixed --- .../api/fir/components/KtFirCallResolver.kt | 6 +- ...FileStructureElementDiagnosticRetriever.kt | 13 ++- .../LLFirModuleLazyDeclarationResolver.kt | 3 +- .../kotlin/backend/common/CodegenUtil.kt | 16 +++- .../kotlin/codegen/PackageCodegenImpl.java | 4 +- .../AbstractDiagnosticCollectorVisitor.kt | 13 ++- .../jetbrains/kotlin/fir/pipeline/analyse.kt | 5 +- .../fir/serialization/FirElementSerializer.kt | 16 ++-- .../kotlin/fir/backend/Fir2IrConverter.kt | 9 +- .../kotlin/fir/backend/Fir2IrVisitor.kt | 78 ++++++++++------ .../FirResolveModularizedTotalKotlinTest.kt | 9 +- .../FirSealedClassInheritorsProcessor.kt | 13 ++- .../FirStatusResolveTransformer.kt | 25 +++--- .../transformers/FirTotalResolveProcessor.kt | 5 +- .../transformers/FirTypeResolveTransformer.kt | 38 ++++---- .../FirDeclarationsResolveTransformer.kt | 37 ++++---- .../FirExpressionsResolveTransformer.kt | 67 ++++++++------ ...erRequiredAnnotationsResolveTransformer.kt | 19 +++- .../src/org/jetbrains/kotlin/fir/Utils.kt | 21 +++-- .../kotlin/util/AnalysisExceptions.kt | 90 +++++++++++++++++++ .../backend/common/phaser/performByIrFile.kt | 12 ++- .../kotlin/backend/jvm/MultifileFacades.kt | 2 + .../org/jetbrains/kotlin/ir/IrFileEntry.kt | 1 + .../jetbrains/kotlin/fir/FirAnalyzerFacade.kt | 8 +- 24 files changed, 363 insertions(+), 147 deletions(-) create mode 100644 compiler/frontend.common/src/org/jetbrains/kotlin/util/AnalysisExceptions.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt index be03736c576..8479c4b1b18 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.analysis.api.fir.components +import org.jetbrains.kotlin.util.SourceCodeAnalysisException import org.jetbrains.kotlin.analysis.api.calls.* import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic import org.jetbrains.kotlin.analysis.api.diagnostics.KtNonBoundToPsiErrorDiagnostic @@ -1223,7 +1224,10 @@ internal class KtFirCallResolver( action() } catch (e: Throwable) { if (shouldIjPlatformExceptionBeRethrown(e)) throw e - buildErrorWithAttachment("Error during resolving call ${element::class.java.name}", cause = e) { + buildErrorWithAttachment( + "Error during resolving call ${element::class.java.name}", + cause = if (e is SourceCodeAnalysisException) e.cause else e, + ) { withPsiEntry("psi", element) element.getOrBuildFir(firResolveSession)?.let { withFirEntry("fir", it) } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt index 14a4c0bcd6d..361dd05a508 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.analysis.collectors.DiagnosticCollectorComponent import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.util.withSourceCodeAnalysisExceptionUnwrapping internal abstract class FileStructureElementDiagnosticRetriever { abstract fun retrieve( @@ -36,8 +37,10 @@ internal class SingleNonLocalDeclarationDiagnosticRetriever( val context = moduleComponents.globalResolveComponents.lockProvider.withWriteLock(firFile) { PersistenceContextCollector.collectContext(sessionHolder, firFile, structureElementDeclaration) } - return collector.collectForStructureElement(structureElementDeclaration) { components -> - Visitor(structureElementDeclaration, context, components) + return withSourceCodeAnalysisExceptionUnwrapping { + collector.collectForStructureElement(structureElementDeclaration) { components -> + Visitor(structureElementDeclaration, context, components) + } } } @@ -102,8 +105,10 @@ internal object FileDiagnosticRetriever : FileStructureElementDiagnosticRetrieve collector: FileStructureElementDiagnosticsCollector, moduleComponents: LLFirModuleResolveComponents, ): FileStructureElementDiagnosticList = - collector.collectForStructureElement(firFile) { components -> - Visitor(components, moduleComponents) + withSourceCodeAnalysisExceptionUnwrapping { + collector.collectForStructureElement(firFile) { components -> + Visitor(components, moduleComponents) + } } private class Visitor( diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt index 88e416f7bda..0f43c515f28 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve +import org.jetbrains.kotlin.util.SourceCodeAnalysisException import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignationWithFile @@ -443,7 +444,7 @@ private fun rethrowWithDetails( appendLine("declaration KtModule: ${moduleData.ktModule::class}") appendLine("declaration platform: ${moduleData.ktModule.platform}") }, - cause = e, + cause = if (e is SourceCodeAnalysisException) e.cause else e, ) { withEntry("KtModule", firDeclarationToResolve.llFirModuleData.ktModule) { it.moduleDescription } withEntry("session", firDeclarationToResolve.llFirSession) { it.toString() } diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt index 8662c590a4d..0fba259e42b 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.util.SourceCodeAnalysisException import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.Errors @@ -233,13 +234,24 @@ object CodegenUtil { } @JvmStatic - fun reportBackendException(exception: Throwable, phase: String, location: String?, additionalMessage: String? = null): Nothing { + fun reportBackendException( + exception: Throwable, + phase: String, + location: String?, + additionalMessage: String? = null, + linesMapping: (Int) -> Pair? = { _ -> null }, + ): Nothing { // CompilationException (the only KotlinExceptionWithAttachments possible here) is already supposed // to have all information about the context. if (exception is KotlinExceptionWithAttachments) throw exception if (exception is ProcessCanceledException) throw exception + val locationWithLineAndOffset = location + ?.let { exception as? SourceCodeAnalysisException } + ?.let { linesMapping(it.source.startOffset) } + ?.let { (line, offset) -> "$location:${line + 1}:${offset + 1}" } + ?: location throw BackendException( - getExceptionMessage("Backend", "Exception during $phase", exception, location) + + getExceptionMessage("Backend", "Exception during $phase", exception, locationWithLineAndOffset) + additionalMessage?.let { "\n" + it }.orEmpty(), exception ) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegenImpl.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegenImpl.java index 180173e8941..61307a85dc0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegenImpl.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackageCodegenImpl.java @@ -75,7 +75,9 @@ public class PackageCodegenImpl implements PackageCodegen { } catch (Throwable e) { VirtualFile vFile = file.getVirtualFile(); - CodegenUtil.reportBackendException(e, "file facade code generation", vFile == null ? null : vFile.getUrl(), null); + CodegenUtil.reportBackendException( + e, "file facade code generation", vFile == null ? null : vFile.getUrl(), null, (it) -> null + ); } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt index ae1796066fb..4922c823d51 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor +import org.jetbrains.kotlin.fir.whileAnalysing import org.jetbrains.kotlin.name.Name abstract class AbstractDiagnosticCollectorVisitor( @@ -270,7 +271,9 @@ abstract class AbstractDiagnosticCollectorVisitor( val existingContext = context context = context.addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall) try { - return block() + return whileAnalysing(qualifiedAccessOrAnnotationCall) { + block() + } } finally { existingContext.dropQualifiedAccessOrAnnotationCall() context = existingContext @@ -283,7 +286,9 @@ abstract class AbstractDiagnosticCollectorVisitor( val existingContext = context context = context.addGetClassCall(getClassCall) try { - return block() + return whileAnalysing(getClassCall) { + block() + } } finally { existingContext.dropGetClassCall() context = existingContext @@ -296,7 +301,9 @@ abstract class AbstractDiagnosticCollectorVisitor( val existingContext = context context = context.addDeclaration(declaration) try { - return block() + return whileAnalysing(declaration) { + block() + } } finally { existingContext.dropDeclaration() context = existingContext diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt index 814858e13af..6b6487b61dd 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor +import org.jetbrains.kotlin.fir.withFileAnalysisExceptionWrapping fun FirSession.runResolution(firFiles: List): Pair> { val resolveProcessor = FirTotalResolveProcessor(this) @@ -21,6 +22,8 @@ fun FirSession.runResolution(firFiles: List): Pair, reporter: DiagnosticReporter) { val collector = FirDiagnosticsCollector.create(this, scopeSession) for (file in firFiles) { - collector.collectDiagnostics(file, reporter) + withFileAnalysisExceptionWrapping(file) { + collector.collectDiagnostics(file, reporter) + } } } diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt index 4753ecbcd8e..cdcbcbbeb62 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt @@ -87,7 +87,7 @@ class FirElementSerializer private constructor( return builder } - fun classProto(klass: FirClass): ProtoBuf.Class.Builder { + fun classProto(klass: FirClass): ProtoBuf.Class.Builder = whileAnalysing(klass) { val builder = ProtoBuf.Class.newBuilder() val regularClass = klass as? FirRegularClass @@ -248,7 +248,7 @@ class FirElementSerializer private constructor( useSiteTarget == AnnotationUseSiteTarget.SETTER_PARAMETER && isSetter } - fun propertyProto(property: FirProperty): ProtoBuf.Property.Builder? { + fun propertyProto(property: FirProperty): ProtoBuf.Property.Builder? = whileAnalysing(property) { if (!extension.shouldSerializeProperty(property)) return null val builder = ProtoBuf.Property.newBuilder() @@ -356,7 +356,7 @@ class FirElementSerializer private constructor( return builder } - fun functionProto(function: FirFunction): ProtoBuf.Function.Builder? { + fun functionProto(function: FirFunction): ProtoBuf.Function.Builder? = whileAnalysing(function) { if (!extension.shouldSerializeFunction(function)) return null val builder = ProtoBuf.Function.newBuilder() @@ -450,7 +450,7 @@ class FirElementSerializer private constructor( return builder } - private fun typeAliasProto(typeAlias: FirTypeAlias): ProtoBuf.TypeAlias.Builder? { + private fun typeAliasProto(typeAlias: FirTypeAlias): ProtoBuf.TypeAlias.Builder? = whileAnalysing(typeAlias) { if (!extension.shouldSerializeTypeAlias(typeAlias)) return null val builder = ProtoBuf.TypeAlias.newBuilder() @@ -497,14 +497,14 @@ class FirElementSerializer private constructor( return builder } - private fun enumEntryProto(enumEntry: FirEnumEntry): ProtoBuf.EnumEntry.Builder { + private fun enumEntryProto(enumEntry: FirEnumEntry): ProtoBuf.EnumEntry.Builder = whileAnalysing(enumEntry) { val builder = ProtoBuf.EnumEntry.newBuilder() builder.name = getSimpleNameIndex(enumEntry.name) extension.serializeEnumEntry(enumEntry, builder) return builder } - private fun constructorProto(constructor: FirConstructor): ProtoBuf.Constructor.Builder { + private fun constructorProto(constructor: FirConstructor): ProtoBuf.Constructor.Builder = whileAnalysing(constructor) { val builder = ProtoBuf.Constructor.newBuilder() val local = createChildSerializer(constructor) @@ -543,7 +543,7 @@ class FirElementSerializer private constructor( private fun valueParameterProto( parameter: FirValueParameter, additionalAnnotations: List = emptyList() - ): ProtoBuf.ValueParameter.Builder { + ): ProtoBuf.ValueParameter.Builder = whileAnalysing(parameter) { val builder = ProtoBuf.ValueParameter.newBuilder() val declaresDefaultValue = parameter.defaultValue != null // TODO: || parameter.isActualParameterWithAnyExpectedDefault @@ -580,7 +580,7 @@ class FirElementSerializer private constructor( return builder } - private fun typeParameterProto(typeParameter: FirTypeParameter): ProtoBuf.TypeParameter.Builder { + private fun typeParameterProto(typeParameter: FirTypeParameter): ProtoBuf.TypeParameter.Builder = whileAnalysing(typeParameter) { val builder = ProtoBuf.TypeParameter.newBuilder() builder.id = getTypeParameterId(typeParameter) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index c0c75cd2057..ccbcab73f84 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.generators.* import org.jetbrains.kotlin.fir.backend.generators.DataClassMembersGenerator import org.jetbrains.kotlin.fir.declarations.* @@ -29,9 +29,6 @@ import org.jetbrains.kotlin.fir.extensions.declarationGenerators import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.generatedMembers import org.jetbrains.kotlin.fir.extensions.generatedNestedClassifiers -import org.jetbrains.kotlin.fir.languageVersionSettings -import org.jetbrains.kotlin.fir.packageFqName -import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer import org.jetbrains.kotlin.fir.signaturer.FirMangler @@ -95,7 +92,9 @@ class Fir2IrConverter( // If we encounter local class / anonymous object here, then we perform all (1)-(5) stages immediately delegatedMemberGenerator.generateBodies() for (firFile in allFirFiles) { - firFile.accept(fir2irVisitor, null) + withFileAnalysisExceptionWrapping(firFile) { + firFile.accept(fir2irVisitor, null) + } } if (irGenerationExtensions.isNotEmpty()) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index da77f5593cc..e470f2bdc87 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -77,7 +77,7 @@ class Fir2IrVisitor( TODO("Should not be here: ${element::class} ${element.render()}") } - override fun visitField(field: FirField, data: Any?): IrField { + override fun visitField(field: FirField, data: Any?): IrField = whileAnalysing(field) { if (field.isSynthetic) { return declarationStorage.getCachedIrDelegateOrBackingField(field)!!.apply { // If this is a property backing field, then it has no separate initializer, @@ -106,13 +106,13 @@ class Fir2IrVisitor( // ================================================================================== - override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Any?): IrElement { + override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Any?): IrElement = whileAnalysing(typeAlias) { val irTypeAlias = classifierStorage.getCachedTypeAlias(typeAlias)!! annotationGenerator.generate(irTypeAlias, typeAlias) return irTypeAlias } - override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Any?): IrElement { + override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Any?): IrElement = whileAnalysing(enumEntry) { val irEnumEntry = classifierStorage.getCachedIrEnumEntry(enumEntry)!! annotationGenerator.generate(irEnumEntry, enumEntry) val correspondingClass = irEnumEntry.correspondingClass @@ -169,7 +169,7 @@ class Fir2IrVisitor( return irEnumEntry } - override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement { + override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement = whileAnalysing(regularClass) { if (regularClass.visibility == Visibilities.Local) { val irParent = conversionScope.parentFromStack() // NB: for implicit types it is possible that local class is already cached @@ -215,7 +215,7 @@ class Fir2IrVisitor( return visitAnonymousObject(anonymousObjectExpression.anonymousObject, data) } - override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): IrElement { + override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): IrElement = whileAnalysing(anonymousObject) { val irParent = conversionScope.parentFromStack() // NB: for implicit types it is possible that anonymous object is already cached val irAnonymousObject = classifierStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent } @@ -248,14 +248,17 @@ class Fir2IrVisitor( // ================================================================================== - override fun visitConstructor(constructor: FirConstructor, data: Any?): IrElement { + override fun visitConstructor(constructor: FirConstructor, data: Any?): IrElement = whileAnalysing(constructor) { val irConstructor = declarationStorage.getCachedIrConstructor(constructor)!! return conversionScope.withFunction(irConstructor) { memberGenerator.convertFunctionContent(irConstructor, constructor, containingClass = conversionScope.containerFirClass()) } } - override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Any?): IrElement { + override fun visitAnonymousInitializer( + anonymousInitializer: FirAnonymousInitializer, + data: Any? + ): IrElement = whileAnalysing(anonymousInitializer) { val irAnonymousInitializer = declarationStorage.getCachedIrAnonymousInitializer(anonymousInitializer)!! declarationStorage.enterScope(irAnonymousInitializer) irAnonymousInitializer.body = convertToIrBlockBody(anonymousInitializer.body!!) @@ -263,7 +266,7 @@ class Fir2IrVisitor( return irAnonymousInitializer } - override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): IrElement { + override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): IrElement = whileAnalysing(simpleFunction) { val irFunction = if (simpleFunction.visibility == Visibilities.Local) { declarationStorage.createIrFunction( simpleFunction, irParent = conversionScope.parent(), predefinedOrigin = IrDeclarationOrigin.LOCAL_FUNCTION, isLocal = true @@ -282,7 +285,10 @@ class Fir2IrVisitor( return visitAnonymousFunction(anonymousFunctionExpression.anonymousFunction, data) } - override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Any?): IrElement { + override fun visitAnonymousFunction( + anonymousFunction: FirAnonymousFunction, + data: Any? + ): IrElement = whileAnalysing(anonymousFunction) { return anonymousFunction.convertWithOffsets { startOffset, endOffset -> val irFunction = declarationStorage.createIrFunction( anonymousFunction, @@ -304,7 +310,7 @@ class Fir2IrVisitor( } } - private fun visitLocalVariable(variable: FirProperty): IrElement { + private fun visitLocalVariable(variable: FirProperty): IrElement = whileAnalysing(variable) { assert(variable.isLocal) val delegate = variable.delegate if (delegate != null) { @@ -354,7 +360,7 @@ class Fir2IrVisitor( this@insertImplicitCast.cast(baseExpression, valueType, expectedType) } - override fun visitProperty(property: FirProperty, data: Any?): IrElement { + override fun visitProperty(property: FirProperty, data: Any?): IrElement = whileAnalysing(property) { if (property.isLocal) return visitLocalVariable(property) val irProperty = declarationStorage.getCachedIrProperty(property) ?: return IrErrorExpressionImpl( @@ -462,11 +468,14 @@ class Fir2IrVisitor( return result } - override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrExpression { + override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrExpression = whileAnalysing(functionCall) { return convertToIrCall(functionCall = functionCall, annotationMode = false) } - override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Any?): IrElement { + override fun visitSafeCallExpression( + safeCallExpression: FirSafeCallExpression, + data: Any? + ): IrElement = whileAnalysing(safeCallExpression) { val explicitReceiverExpression = convertToIrExpression(safeCallExpression.receiver) val (receiverVariable, variableSymbol) = components.createTemporaryVariableForSafeCallConstruction( @@ -493,7 +502,7 @@ class Fir2IrVisitor( return callGenerator.convertToIrConstructorCall(annotation) } - override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: Any?): IrElement { + override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: Any?): IrElement = whileAnalysing(annotationCall) { return callGenerator.convertToIrConstructorCall(annotationCall) } @@ -508,7 +517,7 @@ class Fir2IrVisitor( private fun convertQualifiedAccessExpression( qualifiedAccessExpression: FirQualifiedAccessExpression, annotationMode: Boolean = false - ) : IrExpression { + ): IrExpression = whileAnalysing(qualifiedAccessExpression) { val explicitReceiverExpression = convertToIrReceiverExpression( qualifiedAccessExpression.explicitReceiver, qualifiedAccessExpression.calleeReference ) @@ -528,7 +537,10 @@ class Fir2IrVisitor( return false } - override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: Any?): IrElement { + override fun visitThisReceiverExpression( + thisReceiverExpression: FirThisReceiverExpression, + data: Any? + ): IrElement = whileAnalysing(thisReceiverExpression) { val calleeReference = thisReceiverExpression.calleeReference val boundSymbol = calleeReference.boundSymbol if (boundSymbol is FirClassSymbol) { @@ -611,7 +623,9 @@ class Fir2IrVisitor( } override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement { - return convertCallableReferenceAccess(callableReferenceAccess, false) + return whileAnalysing(callableReferenceAccess) { + convertCallableReferenceAccess(callableReferenceAccess, false) + } } private fun convertCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, isDelegate: Boolean): IrElement { @@ -625,15 +639,19 @@ class Fir2IrVisitor( ) } - override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: Any?): IrElement { + override fun visitVariableAssignment( + variableAssignment: FirVariableAssignment, + data: Any? + ): IrElement = whileAnalysing(variableAssignment) { val explicitReceiverExpression = convertToIrReceiverExpression( variableAssignment.explicitReceiver, variableAssignment.calleeReference ) return callGenerator.convertToIrSetCall(variableAssignment, explicitReceiverExpression) } - override fun visitConstExpression(constExpression: FirConstExpression, data: Any?): IrElement = - constExpression.toIrConst(constExpression.typeRef.toIrType()) + override fun visitConstExpression(constExpression: FirConstExpression, data: Any?): IrElement { + return constExpression.toIrConst(constExpression.typeRef.toIrType()) + } // ================================================================================== @@ -1210,7 +1228,10 @@ class Fir2IrVisitor( override fun visitComparisonExpression(comparisonExpression: FirComparisonExpression, data: Any?): IrElement = operatorGenerator.convertComparisonExpression(comparisonExpression) - override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: Any?): IrElement { + override fun visitStringConcatenationCall( + stringConcatenationCall: FirStringConcatenationCall, + data: Any? + ): IrElement = whileAnalysing(stringConcatenationCall) { return stringConcatenationCall.convertWithOffsets { startOffset, endOffset -> val arguments = mutableListOf() val sb = StringBuilder() @@ -1258,10 +1279,12 @@ class Fir2IrVisitor( } override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: Any?): IrElement { - return operatorGenerator.convertEqualityOperatorCall(equalityOperatorCall) + return whileAnalysing(equalityOperatorCall) { + operatorGenerator.convertEqualityOperatorCall(equalityOperatorCall) + } } - override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: Any?): IrElement { + override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: Any?): IrElement = whileAnalysing(checkNotNullCall) { return checkNotNullCall.convertWithOffsets { startOffset, endOffset -> IrCallImpl( startOffset, endOffset, @@ -1277,7 +1300,7 @@ class Fir2IrVisitor( } } - override fun visitGetClassCall(getClassCall: FirGetClassCall, data: Any?): IrElement { + override fun visitGetClassCall(getClassCall: FirGetClassCall, data: Any?): IrElement = whileAnalysing(getClassCall) { val argument = getClassCall.argument val irType = getClassCall.typeRef.toIrType() val irClassType = @@ -1342,11 +1365,14 @@ class Fir2IrVisitor( } } - override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: Any?): IrElement { + override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: Any?): IrElement = whileAnalysing(arrayOfCall) { return convertToArrayOfCall(arrayOfCall, annotationMode = false) } - override fun visitAugmentedArraySetCall(augmentedArraySetCall: FirAugmentedArraySetCall, data: Any?): IrElement { + override fun visitAugmentedArraySetCall( + augmentedArraySetCall: FirAugmentedArraySetCall, + data: Any? + ): IrElement = whileAnalysing(augmentedArraySetCall) { return augmentedArraySetCall.convertWithOffsets { startOffset, endOffset -> IrErrorCallExpressionImpl( startOffset, endOffset, irBuiltIns.unitType, diff --git a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt index d15540e9c45..84e06894c14 100644 --- a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt +++ b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt @@ -335,9 +335,10 @@ class FirCheckersRunnerTransformer(private val diagnosticCollector: AbstractDiag return element } - override fun transformFile(file: FirFile, data: Nothing?): FirFile { - val reporter = DiagnosticReporterFactory.createPendingReporter() - diagnosticCollector.collectDiagnostics(file, reporter) - return file + override fun transformFile(file: FirFile, data: Nothing?): FirFile = file.also { + withFileAnalysisExceptionWrapping(file) { + val reporter = DiagnosticReporterFactory.createPendingReporter() + diagnosticCollector.collectDiagnostics(file, reporter) + } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt index 3f2720539ff..2905c3a4d6c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.transformSingle +import org.jetbrains.kotlin.fir.withFileAnalysisExceptionWrapping import org.jetbrains.kotlin.name.ClassId class FirSealedClassInheritorsProcessor( @@ -38,8 +39,16 @@ class FirSealedClassInheritorsProcessor( override fun process(files: Collection) { val sealedClassInheritorsMap = mutableMapOf>() val inheritorsCollector = InheritorsCollector(session) - files.forEach { it.accept(inheritorsCollector, sealedClassInheritorsMap) } - files.forEach { it.transformSingle(InheritorsTransformer(sealedClassInheritorsMap), null) } + files.forEach { + withFileAnalysisExceptionWrapping(it) { + it.accept(inheritorsCollector, sealedClassInheritorsMap) + } + } + files.forEach { + withFileAnalysisExceptionWrapping(it) { + it.transformSingle(InheritorsTransformer(sealedClassInheritorsMap), null) + } + } } class InheritorsCollector(val session: FirSession) : FirDefaultVisitor>>() { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt index 0029ed4bbb8..1170308b284 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolveTransformer.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.toSymbol import org.jetbrains.kotlin.fir.visitors.transformSingle +import org.jetbrains.kotlin.fir.whileAnalysing class FirStatusResolveProcessor( session: FirSession, @@ -104,7 +105,7 @@ open class FirStatusResolveTransformer( override fun transformRegularClass( regularClass: FirRegularClass, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(regularClass) { val computationStatus = statusComputationSession.startComputing(regularClass) forceResolveStatusesOfSupertypes(regularClass) /* @@ -166,7 +167,7 @@ open class FirDesignatedStatusResolveTransformer( override fun transformRegularClass( regularClass: FirRegularClass, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(regularClass) { if (shouldSkipClass(regularClass)) return regularClass regularClass.symbol.lazyResolveToPhase(FirResolvePhase.TYPES) val classLocated = this.classLocated @@ -290,7 +291,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformDeclaration( declaration: FirDeclaration, data: FirResolvedDeclarationStatus? - ): FirDeclaration { + ): FirDeclaration = whileAnalysing(declaration) { return when (declaration) { is FirCallableDeclaration -> { if (declaration is FirFunction) { @@ -309,7 +310,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformTypeAlias( typeAlias: FirTypeAlias, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(typeAlias) { typeAlias.typeParameters.forEach { transformDeclaration(it, data) } typeAlias.transformStatus(this, statusResolver.resolveStatus(typeAlias, containingClass, isLocal = false)) return transformDeclaration(typeAlias, data) as FirTypeAlias @@ -323,7 +324,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformAnonymousObject( anonymousObject: FirAnonymousObject, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(anonymousObject) { anonymousObject.transformStatus( this, FirResolvedDeclarationStatusImpl( @@ -369,7 +370,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformClass( klass: FirClass, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(klass) { return storeClass(klass) { klass.typeParameters.forEach { it.transformSingle(this, data) } transformDeclarationContent(klass, data) @@ -447,7 +448,7 @@ abstract class AbstractFirStatusResolveTransformer( propertyAccessor: FirPropertyAccessor, containingProperty: FirProperty, overriddenStatuses: List = emptyList(), - ) { + ): Unit = whileAnalysing(propertyAccessor) { propertyAccessor.transformStatus( this, statusResolver.resolveStatus( @@ -465,7 +466,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformConstructor( constructor: FirConstructor, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(constructor) { constructor.transformStatus(this, statusResolver.resolveStatus(constructor, containingClass, isLocal = false)) calculateDeprecations(constructor) return transformDeclaration(constructor, data) as FirStatement @@ -474,7 +475,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformSimpleFunction( simpleFunction: FirSimpleFunction, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(simpleFunction) { val resolvedStatus = statusResolver.resolveStatus(simpleFunction, containingClass, isLocal = false) simpleFunction.transformStatus(this, resolvedStatus) calculateDeprecations(simpleFunction) @@ -484,7 +485,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformProperty( property: FirProperty, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(property) { val overridden = statusResolver.getOverriddenProperties(property, containingClass) val overriddenProperties = overridden.map { @@ -519,7 +520,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformField( field: FirField, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(field) { field.transformStatus(this, statusResolver.resolveStatus(field, containingClass, isLocal = false)) calculateDeprecations(field) return transformDeclaration(field, data) as FirField @@ -532,7 +533,7 @@ abstract class AbstractFirStatusResolveTransformer( override fun transformEnumEntry( enumEntry: FirEnumEntry, data: FirResolvedDeclarationStatus? - ): FirStatement { + ): FirStatement = whileAnalysing(enumEntry) { enumEntry.transformStatus(this, statusResolver.resolveStatus(enumEntry, containingClass, isLocal = false)) calculateDeprecations(enumEntry) return transformDeclaration(enumEntry, data) as FirEnumEntry diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt index b8772c0598a..906d93bac85 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitTyp import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveProcessor import org.jetbrains.kotlin.fir.resolve.transformers.mpp.FirExpectActualMatcherProcessor import org.jetbrains.kotlin.fir.resolve.transformers.plugin.* +import org.jetbrains.kotlin.fir.withFileAnalysisExceptionWrapping class FirTotalResolveProcessor(session: FirSession) { val scopeSession: ScopeSession = ScopeSession() @@ -30,7 +31,9 @@ class FirTotalResolveProcessor(session: FirSession) { when (processor) { is FirTransformerBasedResolveProcessor -> { for (file in files) { - processor.processFile(file) + withFileAnalysisExceptionWrapping(file) { + processor.processFile(file) + } } } is FirGlobalResolveProcessor -> { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt index 408fb92f8f1..3e3b0b2af18 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTypeResolveTransformer.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef +import org.jetbrains.kotlin.fir.whileAnalysing class FirTypeResolveProcessor( session: FirSession, @@ -74,16 +75,18 @@ open class FirTypeResolveTransformer( } override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): FirStatement { - withClassDeclarationCleanup(classDeclarationsStack, regularClass) { - withScopeCleanup { - regularClass.addTypeParametersScope() - regularClass.typeParameters.forEach { - it.accept(this, data) + whileAnalysing(regularClass) { + withClassDeclarationCleanup(classDeclarationsStack, regularClass) { + withScopeCleanup { + regularClass.addTypeParametersScope() + regularClass.typeParameters.forEach { + it.accept(this, data) + } + unboundCyclesInTypeParametersSupertypes(regularClass) } - unboundCyclesInTypeParametersSupertypes(regularClass) - } - return resolveClassContent(regularClass, data) + return resolveClassContent(regularClass, data) + } } } @@ -93,21 +96,21 @@ open class FirTypeResolveTransformer( } } - override fun transformConstructor(constructor: FirConstructor, data: Any?): FirConstructor { + override fun transformConstructor(constructor: FirConstructor, data: Any?): FirConstructor = whileAnalysing(constructor) { return withScopeCleanup { constructor.addTypeParametersScope() transformDeclaration(constructor, data) } as FirConstructor } - override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Any?): FirTypeAlias { + override fun transformTypeAlias(typeAlias: FirTypeAlias, data: Any?): FirTypeAlias = whileAnalysing(typeAlias) { return withScopeCleanup { typeAlias.addTypeParametersScope() transformDeclaration(typeAlias, data) } as FirTypeAlias } - override fun transformEnumEntry(enumEntry: FirEnumEntry, data: Any?): FirEnumEntry { + override fun transformEnumEntry(enumEntry: FirEnumEntry, data: Any?): FirEnumEntry = whileAnalysing(enumEntry) { enumEntry.transformReturnTypeRef(this, data) enumEntry.transformTypeParameters(this, data) enumEntry.transformAnnotations(this, data) @@ -118,7 +121,7 @@ open class FirTypeResolveTransformer( return receiverParameter.transformAnnotations(this, data).transformTypeRef(this, data) } - override fun transformProperty(property: FirProperty, data: Any?): FirProperty { + override fun transformProperty(property: FirProperty, data: Any?): FirProperty = whileAnalysing(property) { return withScopeCleanup { property.addTypeParametersScope() property.transformTypeParameters(this, data) @@ -150,14 +153,17 @@ open class FirTypeResolveTransformer( property.setter?.valueParameters?.map { it.transformReturnTypeRef(StoreType, property.returnTypeRef) } } - override fun transformField(field: FirField, data: Any?): FirField { + override fun transformField(field: FirField, data: Any?): FirField = whileAnalysing(field) { return withScopeCleanup { field.transformReturnTypeRef(this, data).transformAnnotations(this, data) field } } - override fun transformSimpleFunction(simpleFunction: FirSimpleFunction, data: Any?): FirSimpleFunction { + override fun transformSimpleFunction( + simpleFunction: FirSimpleFunction, + data: Any? + ): FirSimpleFunction = whileAnalysing(simpleFunction) { return withScopeCleanup { simpleFunction.addTypeParametersScope() transformDeclaration(simpleFunction, data).also { @@ -208,7 +214,7 @@ open class FirTypeResolveTransformer( } } - override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): FirStatement { + override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): FirStatement = whileAnalysing(valueParameter) { valueParameter.transformReturnTypeRef(this, data) valueParameter.transformAnnotations(this, data) valueParameter.transformVarargTypeToArrayType() @@ -224,7 +230,7 @@ open class FirTypeResolveTransformer( return annotation } - override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Any?): FirStatement { + override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: Any?): FirStatement = whileAnalysing(annotationCall) { return transformAnnotation(annotationCall, data) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 34a6708d30e..5e863f2022e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -111,7 +111,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve } } - override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty { + override fun transformProperty(property: FirProperty, data: ResolutionMode): FirProperty = whileAnalysing(property) { require(property !is FirSyntheticProperty) { "Synthetic properties should not be processed by body transformers" } if (property.isLocal) { @@ -207,7 +207,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve } } - override fun transformField(field: FirField, data: ResolutionMode): FirField { + override fun transformField(field: FirField, data: ResolutionMode): FirField = whileAnalysing(field) { val returnTypeRef = field.returnTypeRef if (implicitTypeOnly) return field if (field.initializerResolved) return field @@ -373,7 +373,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve return delegateExpression } - private fun transformLocalVariable(variable: FirProperty): FirProperty { + private fun transformLocalVariable(variable: FirProperty): FirProperty = whileAnalysing(variable) { assert(variable.isLocal) val delegate = variable.delegate @@ -455,7 +455,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve accessor: FirPropertyAccessor, enhancedTypeRef: FirTypeRef, owner: FirProperty - ) { + ): Unit = whileAnalysing(accessor) { context.withPropertyAccessor(owner, accessor, components) { if (accessor is FirDefaultPropertyAccessor || accessor.body == null) { transformFunction(accessor, withExpectedType(enhancedTypeRef)) @@ -490,8 +490,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve ) } - override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement { - context.withContainingClass(regularClass) { + override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement = whileAnalysing(regularClass) { + return context.withContainingClass(regularClass) { if (regularClass.isLocal && regularClass !in context.targetedLocalClasses) { return regularClass.runAllPhasesForLocalClass( transformer, @@ -503,7 +503,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve } doTransformTypeParameters(regularClass) - return doTransformRegularClass(regularClass, data) + doTransformRegularClass(regularClass, data) } } @@ -519,7 +519,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve return result } - override fun transformTypeAlias(typeAlias: FirTypeAlias, data: ResolutionMode): FirTypeAlias { + override fun transformTypeAlias(typeAlias: FirTypeAlias, data: ResolutionMode): FirTypeAlias = whileAnalysing(typeAlias) { if (typeAlias.isLocal && typeAlias !in context.targetedLocalClasses) { return typeAlias.runAllPhasesForLocalClass( transformer, @@ -559,7 +559,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve override fun transformAnonymousObject( anonymousObject: FirAnonymousObject, data: ResolutionMode - ): FirStatement { + ): FirStatement = whileAnalysing(anonymousObject) { if (anonymousObject !in context.targetedLocalClasses) { return anonymousObject.runAllPhasesForLocalClass( transformer, @@ -617,7 +617,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve override fun transformSimpleFunction( simpleFunction: FirSimpleFunction, data: ResolutionMode - ): FirSimpleFunction { + ): FirSimpleFunction = whileAnalysing(simpleFunction) { if (simpleFunction.bodyResolved) { return simpleFunction } @@ -681,7 +681,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve override fun transformFunction( function: FirFunction, data: ResolutionMode - ): FirStatement { + ): FirStatement = whileAnalysing(function) { val functionIsNotAnalyzed = !function.bodyResolved if (functionIsNotAnalyzed) { dataFlowAnalyzer.enterFunction(function) @@ -696,7 +696,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve } as FirStatement } - override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor { + override fun transformConstructor(constructor: FirConstructor, data: ResolutionMode): FirConstructor = whileAnalysing(constructor) { if (implicitTypeOnly) return constructor val container = context.containerIfAny as? FirRegularClass if (constructor.isPrimary && container?.classKind == ClassKind.ANNOTATION_CLASS) { @@ -737,7 +737,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve override fun transformAnonymousInitializer( anonymousInitializer: FirAnonymousInitializer, data: ResolutionMode - ): FirAnonymousInitializer { + ): FirAnonymousInitializer = whileAnalysing(anonymousInitializer) { if (implicitTypeOnly) return anonymousInitializer dataFlowAnalyzer.enterInitBlock(anonymousInitializer) return context.withAnonymousInitializer(anonymousInitializer, session) { @@ -749,7 +749,10 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve } } - override fun transformValueParameter(valueParameter: FirValueParameter, data: ResolutionMode): FirStatement { + override fun transformValueParameter( + valueParameter: FirValueParameter, + data: ResolutionMode + ): FirStatement = whileAnalysing(valueParameter) { dataFlowAnalyzer.enterValueParameter(valueParameter) val result = context.withValueParameter(valueParameter, session) { transformDeclarationContent( @@ -768,7 +771,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve override fun transformAnonymousFunction( anonymousFunction: FirAnonymousFunction, data: ResolutionMode - ): FirStatement { + ): FirStatement = whileAnalysing(anonymousFunction) { // Either ContextDependent, ContextIndependent or WithExpectedType could be here if (data !is ResolutionMode.LambdaResolution) { anonymousFunction.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent) @@ -1019,7 +1022,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve override fun transformBackingField( backingField: FirBackingField, data: ResolutionMode, - ): FirStatement { + ): FirStatement = whileAnalysing(backingField) { val propertyType = data.expectedType val initializerData = if (backingField.returnTypeRef is FirResolvedTypeRef) { withExpectedType(backingField.returnTypeRef) @@ -1123,7 +1126,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve return element } - override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): FirStatement { + override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): FirStatement = whileAnalysing(valueParameter) { if (valueParameter.returnTypeRef is FirImplicitTypeRef) { valueParameter.transformReturnTypeRef( StoreType, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index b68b7e4da45..82981405443 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -84,7 +84,9 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformQualifiedAccessExpression( qualifiedAccessExpression: FirQualifiedAccessExpression, data: ResolutionMode, - ): FirStatement = transformQualifiedAccessExpression(qualifiedAccessExpression, data, isUsedAsReceiver = false) + ): FirStatement = whileAnalysing(qualifiedAccessExpression) { + transformQualifiedAccessExpression(qualifiedAccessExpression, data, isUsedAsReceiver = false) + } fun transformQualifiedAccessExpression( qualifiedAccessExpression: FirQualifiedAccessExpression, @@ -317,23 +319,25 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT safeCallExpression: FirSafeCallExpression, data: ResolutionMode ): FirStatement { - withContainingSafeCallExpression(safeCallExpression) { - safeCallExpression.transformAnnotations(this, ResolutionMode.ContextIndependent) - safeCallExpression.transformReceiver(this, ResolutionMode.ContextIndependent) + whileAnalysing(safeCallExpression) { + withContainingSafeCallExpression(safeCallExpression) { + safeCallExpression.transformAnnotations(this, ResolutionMode.ContextIndependent) + safeCallExpression.transformReceiver(this, ResolutionMode.ContextIndependent) - val receiver = safeCallExpression.receiver + val receiver = safeCallExpression.receiver - dataFlowAnalyzer.enterSafeCallAfterNullCheck(safeCallExpression) + dataFlowAnalyzer.enterSafeCallAfterNullCheck(safeCallExpression) - safeCallExpression.apply { - checkedSubjectRef.value.propagateTypeFromOriginalReceiver(receiver, components.session, components.file) - transformSelector(this@FirExpressionsResolveTransformer, data) - propagateTypeFromQualifiedAccessAfterNullCheck(receiver, session, context.file) + safeCallExpression.apply { + checkedSubjectRef.value.propagateTypeFromOriginalReceiver(receiver, components.session, components.file) + transformSelector(this@FirExpressionsResolveTransformer, data) + propagateTypeFromQualifiedAccessAfterNullCheck(receiver, session, context.file) + } + + dataFlowAnalyzer.exitSafeCall(safeCallExpression) + + return safeCallExpression } - - dataFlowAnalyzer.exitSafeCall(safeCallExpression) - - return safeCallExpression } } @@ -354,7 +358,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT return checkedSafeCallSubject } - override fun transformFunctionCall(functionCall: FirFunctionCall, data: ResolutionMode): FirStatement { + override fun transformFunctionCall(functionCall: FirFunctionCall, data: ResolutionMode): FirStatement = whileAnalysing(functionCall) { val calleeReference = functionCall.calleeReference if ( (calleeReference is FirResolvedNamedReference || calleeReference is FirErrorNamedReference) && @@ -513,7 +517,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformComparisonExpression( comparisonExpression: FirComparisonExpression, data: ResolutionMode - ): FirStatement { + ): FirStatement = whileAnalysing(comparisonExpression) { return (comparisonExpression.transformChildren(transformer, ResolutionMode.ContextIndependent) as FirComparisonExpression).also { it.resultType = comparisonExpression.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type) dataFlowAnalyzer.exitComparisonExpressionCall(it) @@ -523,7 +527,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformAssignmentOperatorStatement( assignmentOperatorStatement: FirAssignmentOperatorStatement, data: ResolutionMode - ): FirStatement { + ): FirStatement = whileAnalysing(assignmentOperatorStatement) { val operation = assignmentOperatorStatement.operation require(operation != FirOperation.ASSIGN) @@ -650,7 +654,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformEqualityOperatorCall( equalityOperatorCall: FirEqualityOperatorCall, data: ResolutionMode - ): FirStatement { + ): FirStatement = whileAnalysing(equalityOperatorCall) { // Currently, we use expectedType=Any? for both operands // In FE1.0, it's only used for the right // But it seems a bit inconsistent (see KT-47409) @@ -817,7 +821,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformBinaryLogicExpression( binaryLogicExpression: FirBinaryLogicExpression, data: ResolutionMode, - ): FirStatement { + ): FirStatement = whileAnalysing(binaryLogicExpression) { val booleanType = binaryLogicExpression.typeRef.resolvedTypeFromPrototype(builtinTypes.booleanType.type) return when (binaryLogicExpression.kind) { LogicOperationKind.AND -> @@ -839,7 +843,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformVariableAssignment( variableAssignment: FirVariableAssignment, data: ResolutionMode, - ): FirStatement { + ): FirStatement = whileAnalysing(variableAssignment) { // val resolvedAssignment = transformCallee(variableAssignment) variableAssignment.transformAnnotations(transformer, ResolutionMode.ContextIndependent) val resolvedAssignment = callResolver.resolveVariableAccessAndSelectCandidate(variableAssignment, isUsedAsReceiver = false) @@ -884,7 +888,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformCallableReferenceAccess( callableReferenceAccess: FirCallableReferenceAccess, data: ResolutionMode, - ): FirStatement { + ): FirStatement = whileAnalysing(callableReferenceAccess) { if (callableReferenceAccess.calleeReference is FirResolvedNamedReference) { return callableReferenceAccess } @@ -922,7 +926,10 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT } } - override fun transformGetClassCall(getClassCall: FirGetClassCall, data: ResolutionMode): FirStatement { + override fun transformGetClassCall( + getClassCall: FirGetClassCall, + data: ResolutionMode + ): FirStatement = whileAnalysing(getClassCall) { getClassCall.transformAnnotations(transformer, ResolutionMode.ContextIndependent) val arg = getClassCall.argument val dataForLhs = if (arg is FirConstExpression<*>) { @@ -1062,7 +1069,10 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT return annotation } - override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: ResolutionMode): FirStatement { + override fun transformAnnotationCall( + annotationCall: FirAnnotationCall, + data: ResolutionMode + ): FirStatement = whileAnalysing(annotationCall) { if (annotationCall.resolved) return annotationCall annotationCall.transformAnnotationTypeRef(transformer, ResolutionMode.ContextIndependent) return context.forAnnotation { @@ -1094,7 +1104,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformDelegatedConstructorCall( delegatedConstructorCall: FirDelegatedConstructorCall, data: ResolutionMode, - ): FirStatement { + ): FirStatement = whileAnalysing(delegatedConstructorCall) { if (transformer.implicitTypeOnly) return delegatedConstructorCall when (delegatedConstructorCall.calleeReference) { is FirResolvedNamedReference, is FirErrorNamedReference -> return delegatedConstructorCall @@ -1209,7 +1219,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT override fun transformAugmentedArraySetCall( augmentedArraySetCall: FirAugmentedArraySetCall, data: ResolutionMode - ): FirStatement { + ): FirStatement = whileAnalysing(augmentedArraySetCall) { /* * a[b] += c can be desugared to: * @@ -1446,7 +1456,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT ) } - override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: ResolutionMode): FirStatement { + override fun transformArrayOfCall(arrayOfCall: FirArrayOfCall, data: ResolutionMode): FirStatement = whileAnalysing(arrayOfCall) { if (data is ResolutionMode.ContextDependent) { arrayOfCall.transformChildren(transformer, data) return arrayOfCall @@ -1457,7 +1467,10 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT return arrayOfCall } - override fun transformStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: ResolutionMode): FirStatement { + override fun transformStringConcatenationCall( + stringConcatenationCall: FirStringConcatenationCall, + data: ResolutionMode + ): FirStatement = whileAnalysing(stringConcatenationCall) { dataFlowAnalyzer.enterCall() stringConcatenationCall.transformChildren(transformer, ResolutionMode.ContextIndependent) dataFlowAnalyzer.exitStringConcatenationCall(stringConcatenationCall) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt index 67fbcd95f68..9eb146167a4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirCompilerRequiredAnnotationsResolveTransformer.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.FirUserTypeRef import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.fir.visitors.transformSingle +import org.jetbrains.kotlin.fir.withFileAnalysisExceptionWrapping import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -47,13 +48,25 @@ class FirCompilerRequiredAnnotationsResolveProcessor( val transformer = FirCompilerRequiredAnnotationsResolveTransformer(session, scopeSession) val registeredPluginAnnotations = session.registeredPluginAnnotations if (!registeredPluginAnnotations.hasRegisteredAnnotations) { - files.forEach { it.transformSingle(transformer, Mode.RegularAnnotations) } + files.forEach { + withFileAnalysisExceptionWrapping(it) { + it.transformSingle(transformer, Mode.RegularAnnotations) + } + } return } if (registeredPluginAnnotations.metaAnnotations.isNotEmpty()) { - files.forEach { it.transformSingle(transformer, Mode.MetaAnnotations) } + files.forEach { + withFileAnalysisExceptionWrapping(it) { + it.transformSingle(transformer, Mode.MetaAnnotations) + } + } + } + files.forEach { + withFileAnalysisExceptionWrapping(it) { + it.transformSingle(transformer, Mode.RegularAnnotations) + } } - files.forEach { it.transformSingle(transformer, Mode.RegularAnnotations) } } @OptIn(FirSymbolProviderInternals::class) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt index 6bdb95696df..4afe2779448 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/Utils.kt @@ -6,16 +6,10 @@ package org.jetbrains.kotlin.fir import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.KtFakeSourceElementKind -import org.jetbrains.kotlin.KtPsiSourceElement -import org.jetbrains.kotlin.KtRealPsiSourceElement +import org.jetbrains.kotlin.* import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibility -import org.jetbrains.kotlin.fakeElement -import org.jetbrains.kotlin.fir.declarations.FirContextReceiver -import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.declarations.FirResolvedDeclarationStatus +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl import org.jetbrains.kotlin.fir.expressions.FirBlock @@ -142,3 +136,14 @@ fun FirDeclarationStatus.copy( this.isFun = isFun } } + +inline fun whileAnalysing(element: FirElement, block: () -> R) = org.jetbrains.kotlin.util.whileAnalysing(element.source, block) + +inline fun withFileAnalysisExceptionWrapping(file: FirFile, block: () -> R): R { + return org.jetbrains.kotlin.util.withFileAnalysisExceptionWrapping( + file.sourceFile?.path, + file.source, + { file.sourceFileLinesMapping?.getLineAndColumnByOffset(it) }, + block, + ) +} diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/util/AnalysisExceptions.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/util/AnalysisExceptions.kt new file mode 100644 index 00000000000..4e76e960aa4 --- /dev/null +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/util/AnalysisExceptions.kt @@ -0,0 +1,90 @@ +/* + * 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.util + +import com.intellij.openapi.diagnostic.ControlFlowException +import com.intellij.openapi.project.IndexNotReadyException +import org.jetbrains.kotlin.AbstractKtSourceElement +import org.jetbrains.kotlin.KtRealSourceElementKind +import org.jetbrains.kotlin.KtSourceElement + +val Throwable.classNameAndMessage get() = "${this::class.qualifiedName}: $message" + +class SourceCodeAnalysisException(val source: KtSourceElement, override val cause: Throwable) : Exception() { + override val message get() = cause.classNameAndMessage +} + +inline fun whileAnalysing(element: KtSourceElement?, block: () -> R): R { + return try { + block() + } catch (throwable: Throwable) { + throw throwable.wrapIntoSourceCodeAnalysisExceptionIfNeeded(element) + } +} + +@PublishedApi +internal fun Throwable.wrapIntoSourceCodeAnalysisExceptionIfNeeded(element: KtSourceElement?) = when (this) { + is SourceCodeAnalysisException -> this + is IndexNotReadyException -> this + is ControlFlowException -> this + is VirtualMachineError -> this + else -> when (element?.kind) { + is KtRealSourceElementKind -> SourceCodeAnalysisException(element, this) + else -> this + } +} + +class FileAnalysisException( + private val path: String, + override val cause: Throwable, + private val lineAndOffset: Pair? = null, +) : Exception() { + override val message + get(): String { + val (line, offset) = lineAndOffset ?: return "Somewhere in file $path: ${cause.classNameAndMessage}" + return "While analysing $path:${line + 1}:${offset + 1}: ${cause.classNameAndMessage}" + } +} + +inline fun withFileAnalysisExceptionWrapping( + filePath: String?, + fileSource: AbstractKtSourceElement?, + crossinline linesMapping: (Int) -> Pair?, + block: () -> R, +): R { + return try { + block() + } catch (throwable: Throwable) { + throw throwable.wrapIntoFileAnalysisExceptionIfNeeded(filePath, fileSource) { linesMapping(it) } + } +} + +@PublishedApi +internal fun Throwable.wrapIntoFileAnalysisExceptionIfNeeded( + filePath: String?, + fileSource: AbstractKtSourceElement?, + linesMapping: (Int) -> Pair?, +) = when { + filePath == null -> this + + this is SourceCodeAnalysisException -> when (fileSource) { + source -> FileAnalysisException(filePath, cause) + else -> FileAnalysisException(filePath, cause, linesMapping(source.startOffset)) + } + + this is IndexNotReadyException -> this + this is ControlFlowException -> this + this is VirtualMachineError -> this + else -> FileAnalysisException(filePath, this) +} + +inline fun withSourceCodeAnalysisExceptionUnwrapping(block: () -> R): R { + return try { + block() + } catch (throwable: Throwable) { + throw if (throwable is SourceCodeAnalysisException) throwable.cause else throwable + } +} diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/performByIrFile.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/performByIrFile.kt index 9b8902b23a9..5e9fcaf85fd 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/performByIrFile.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/phaser/performByIrFile.kt @@ -65,7 +65,11 @@ private class PerformByIrFilePhase( phase.invoke(phaseConfig, filePhaserState, context, irFile) } } catch (e: Throwable) { - CodegenUtil.reportBackendException(e, "IR lowering", irFile.fileEntry.name) + CodegenUtil.reportBackendException(e, "IR lowering", irFile.fileEntry.name) { offset -> + irFile.fileEntry.takeIf { it.supportsDebugInfo }?.let { + it.getLineNumber(offset) to it.getColumnNumber(offset) + } + } } } @@ -110,7 +114,11 @@ private class PerformByIrFilePhase( executor.awaitTermination(1, TimeUnit.DAYS) // Wait long enough thrownFromThread.get()?.let { (e, irFile) -> - CodegenUtil.reportBackendException(e, "Experimental parallel IR backend", irFile.fileEntry.name) + CodegenUtil.reportBackendException(e, "Experimental parallel IR backend", irFile.fileEntry.name) { offset -> + irFile.fileEntry.takeIf { it.supportsDebugInfo }?.let { + it.getLineNumber(offset) to it.getColumnNumber(offset) + } + } } // Presumably each thread has run through the same list of phases. diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MultifileFacades.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MultifileFacades.kt index ce2c27920b3..493b2f44011 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MultifileFacades.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MultifileFacades.kt @@ -24,6 +24,8 @@ class MultifileFacadeFileEntry( override val maxOffset: Int get() = UNDEFINED_OFFSET + override val supportsDebugInfo get() = false + override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo = error("Multifile facade doesn't support debug info: $className") diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrFileEntry.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrFileEntry.kt index 62e2ebf19ee..d8a86433102 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrFileEntry.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrFileEntry.kt @@ -20,6 +20,7 @@ data class SourceRangeInfo( interface IrFileEntry { val name: String val maxOffset: Int + val supportsDebugInfo: Boolean get() = true fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo fun getLineNumber(offset: Int): Int fun getColumnNumber(offset: Int): Int diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt index 9b465b6f554..3b29614e937 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt @@ -93,9 +93,11 @@ class FirAnalyzerFacade( val collector = FirDiagnosticsCollector.create(session, scopeSession) collectedDiagnostics = buildMap { for (file in firFiles!!) { - val reporter = DiagnosticReporterFactory.createPendingReporter() - collector.collectDiagnostics(file, reporter) - put(file, reporter.diagnostics) + withFileAnalysisExceptionWrapping(file) { + val reporter = DiagnosticReporterFactory.createPendingReporter() + collector.collectDiagnostics(file, reporter) + put(file, reporter.diagnostics) + } } } return collectedDiagnostics!!