From c9df6aff5f1a7cf1c602d134b88d4cd4c6c3e47b Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Mon, 18 Sep 2023 16:15:11 +0200 Subject: [PATCH] [LL FIR] do not crash on attempt to resolve class initializer in case of class clash ^KT-61788 Fixed --- .../low/level/api/fir/api/FirDesignation.kt | 12 ++++---- ...extCollectingDiagnosticCollectorVisitor.kt | 5 ++-- .../level/api/fir/util/containingFileUtils.kt | 2 +- .../level/api/fir/util/declarationUtils.kt | 20 +++---------- .../declarations/initializerConflict.kt | 11 +++++++ .../declarations/initializerConflict.txt | 30 +++++++++++++++++++ ...ContentRootGetOrBuildFirTestGenerated.java | 6 ++++ .../fir/SourceGetOrBuildFirTestGenerated.java | 6 ++++ 8 files changed, 66 insertions(+), 26 deletions(-) create mode 100644 analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.kt create mode 100644 analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.txt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/FirDesignation.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/FirDesignation.kt index 1fad1cd65fb..5685a4a043b 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/FirDesignation.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/FirDesignation.kt @@ -8,11 +8,9 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.api import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.nullableJavaSymbolProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder -import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingClass +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingClassId import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getContainingFile -import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry -import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment -import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptDependentDeclaration import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError import org.jetbrains.kotlin.builtins.StandardNames @@ -26,9 +24,11 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptDependentDeclaration +import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment +import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment class FirDesignationWithFile( path: List, @@ -105,7 +105,7 @@ private fun collectDesignationPath(target: FirElementWithResolveState): List { - val containingClassId = target.containingClass().symbol.classId + val containingClassId = target.containingClassId() if (containingClassId.isLocal) return null return collectDesignationPathWithContainingClass(target, containingClassId) } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/fir/ContextCollectingDiagnosticCollectorVisitor.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/fir/ContextCollectingDiagnosticCollectorVisitor.kt index 48b7746b9e2..65d6a798383 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/fir/ContextCollectingDiagnosticCollectorVisitor.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/fir/ContextCollectingDiagnosticCollectorVisitor.kt @@ -8,14 +8,13 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir import org.jetbrains.kotlin.analysis.low.level.api.fir.ContextByDesignationCollector import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation -import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingClass +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingClassId import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContextForProvider import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.utils.classId import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry @@ -65,7 +64,7 @@ internal object PersistenceContextCollector { is FirClassLikeDeclaration -> declaration.symbol.classId.isLocal is FirCallableDeclaration -> declaration.symbol.callableId.isLocal is FirDanglingModifierList -> declaration.containingClass()?.classId?.isLocal == true - is FirAnonymousInitializer -> declaration.containingClass().classId.isLocal + is FirAnonymousInitializer -> declaration.containingClassId().isLocal is FirScript, is FirCodeFragment -> false else -> errorWithAttachment("Unsupported declaration ${declaration::class}") { withFirEntry("declaration", declaration) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/containingFileUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/containingFileUtils.kt index d208bcdc166..e977f5d6d94 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/containingFileUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/containingFileUtils.kt @@ -25,7 +25,7 @@ fun FirElementWithResolveState.getContainingFile(): FirFile? { is FirBackingField -> propertySymbol.fir.getContainingFile() is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol) is FirClassLikeDeclaration -> provider.getFirClassifierContainerFileIfAny(symbol) - is FirAnonymousInitializer -> containingClass().getContainingFile() + is FirAnonymousInitializer -> provider.getFirClassifierContainerFileIfAny(containingClassId()) is FirDanglingModifierList, is FirCodeFragment -> { val ktFile = psi?.containingFile as? KtFile ?: error("File for dangling modifier list cannot be null") diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt index 3851605e158..922937b9b06 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt @@ -15,15 +15,13 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.containin import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirProvider -import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.realPsi import org.jetbrains.kotlin.fir.resolve.providers.FirProvider -import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry -import org.jetbrains.kotlin.fir.utils.exceptions.withFirLookupTagEntry +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.parameterIndex @@ -174,26 +172,16 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider( return candidate?.takeIf { it.psi == this } } -fun FirAnonymousInitializer.containingClass(): FirRegularClass { +fun FirAnonymousInitializer.containingClassId(): ClassId { val dispatchReceiverType = this.dispatchReceiverType checkWithAttachment( condition = dispatchReceiverType != null, message = { "dispatchReceiverType for ${FirAnonymousInitializer::class.simpleName} modifier cannot be null" }, ) { - withFirEntry("initializer", this@containingClass) + withFirEntry("initializer", this@containingClassId) } - val lookupTag = dispatchReceiverType.lookupTag - val dispatchReceiverSymbol = lookupTag.toSymbol(llFirSession) - checkWithAttachment( - condition = dispatchReceiverSymbol != null, - message = { "symbol for ${FirAnonymousInitializer::class.simpleName} cannot be null" }, - ) { - withFirEntry("initializer", this@containingClass) - withFirLookupTagEntry("tag", lookupTag) - } - - return dispatchReceiverSymbol.fir as FirRegularClass + return dispatchReceiverType.lookupTag.classId } val ORIGINAL_DECLARATION_KEY = com.intellij.openapi.util.Key("ORIGINAL_DECLARATION_KEY") diff --git a/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.kt b/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.kt new file mode 100644 index 00000000000..1ee2ad45122 --- /dev/null +++ b/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.kt @@ -0,0 +1,11 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtClassInitializer + +package one.two + +class A +typealias Foo = A +class Foo { + init { + val i = 1 + } +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.txt b/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.txt new file mode 100644 index 00000000000..7bc845a012b --- /dev/null +++ b/analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.txt @@ -0,0 +1,30 @@ +KT element: KtClassInitializer +FIR element: FirAnonymousInitializerImpl +FIR source kind: KtRealSourceElementKind + +FIR element rendered: +init { + [ResolvedTo(RAW_FIR)] lval i: R|kotlin/Int| = Int(1) +} + +FIR FILE: +FILE: [ResolvedTo(IMPORTS)] initializerConflict.kt + package one.two + + public final [ResolvedTo(STATUS)] class A : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=A] constructor(): R|one/two/A| { + LAZY_super + } + + } + public? final [ResolvedTo(SUPER_TYPES)] typealias Foo = R|one/two/A| + public final [ResolvedTo(STATUS)] class Foo : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=Foo] constructor(): R|one/two/Foo| { + LAZY_super + } + + init { + [ResolvedTo(RAW_FIR)] lval i: R|kotlin/Int| = Int(1) + } + + } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/OutOfContentRootGetOrBuildFirTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/OutOfContentRootGetOrBuildFirTestGenerated.java index 5904ff92117..22dc92b5a7f 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/OutOfContentRootGetOrBuildFirTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/OutOfContentRootGetOrBuildFirTestGenerated.java @@ -513,6 +513,12 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon runTest("analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructuringEntry.kt"); } + @Test + @TestMetadata("initializerConflict.kt") + public void testInitializerConflict() throws Exception { + runTest("analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.kt"); + } + @Test @TestMetadata("kt60387.kt") public void testKt60387() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/SourceGetOrBuildFirTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/SourceGetOrBuildFirTestGenerated.java index a5527b81cdc..d383a30da2c 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/SourceGetOrBuildFirTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/SourceGetOrBuildFirTestGenerated.java @@ -513,6 +513,12 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi runTest("analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructuringEntry.kt"); } + @Test + @TestMetadata("initializerConflict.kt") + public void testInitializerConflict() throws Exception { + runTest("analysis/low-level-api-fir/testData/getOrBuildFir/declarations/initializerConflict.kt"); + } + @Test @TestMetadata("kt60387.kt") public void testKt60387() throws Exception {