[LL FIR] do not crash on attempt to resolve class initializer in case of class clash

^KT-61788 Fixed
This commit is contained in:
Dmitrii Gridin
2023-09-18 16:15:11 +02:00
committed by Space Team
parent e3ad946d23
commit c9df6aff5f
8 changed files with 66 additions and 26 deletions
@@ -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.providers.nullableJavaSymbolProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession 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.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.analysis.low.level.api.fir.util.getContainingFile
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptDependentDeclaration
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
import org.jetbrains.kotlin.builtins.StandardNames 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.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toSymbol 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.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.ClassId 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( class FirDesignationWithFile(
path: List<FirRegularClass>, path: List<FirRegularClass>,
@@ -105,7 +105,7 @@ private fun collectDesignationPath(target: FirElementWithResolveState): List<Fir
} }
is FirAnonymousInitializer -> { is FirAnonymousInitializer -> {
val containingClassId = target.containingClass().symbol.classId val containingClassId = target.containingClassId()
if (containingClassId.isLocal) return null if (containingClassId.isLocal) return null
return collectDesignationPathWithContainingClass(target, containingClassId) return collectDesignationPathWithContainingClass(target, containingClassId)
} }
@@ -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.ContextByDesignationCollector
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile 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.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.FirElement
import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirElementWithResolveState
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContextForProvider import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContextForProvider
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.resolve.SessionHolder
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
@@ -65,7 +64,7 @@ internal object PersistenceContextCollector {
is FirClassLikeDeclaration -> declaration.symbol.classId.isLocal is FirClassLikeDeclaration -> declaration.symbol.classId.isLocal
is FirCallableDeclaration -> declaration.symbol.callableId.isLocal is FirCallableDeclaration -> declaration.symbol.callableId.isLocal
is FirDanglingModifierList -> declaration.containingClass()?.classId?.isLocal == true is FirDanglingModifierList -> declaration.containingClass()?.classId?.isLocal == true
is FirAnonymousInitializer -> declaration.containingClass().classId.isLocal is FirAnonymousInitializer -> declaration.containingClassId().isLocal
is FirScript, is FirCodeFragment -> false is FirScript, is FirCodeFragment -> false
else -> errorWithAttachment("Unsupported declaration ${declaration::class}") { else -> errorWithAttachment("Unsupported declaration ${declaration::class}") {
withFirEntry("declaration", declaration) withFirEntry("declaration", declaration)
@@ -25,7 +25,7 @@ fun FirElementWithResolveState.getContainingFile(): FirFile? {
is FirBackingField -> propertySymbol.fir.getContainingFile() is FirBackingField -> propertySymbol.fir.getContainingFile()
is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol) is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol)
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFileIfAny(symbol) is FirClassLikeDeclaration -> provider.getFirClassifierContainerFileIfAny(symbol)
is FirAnonymousInitializer -> containingClass().getContainingFile() is FirAnonymousInitializer -> provider.getFirClassifierContainerFileIfAny(containingClassId())
is FirDanglingModifierList, is FirCodeFragment -> { is FirDanglingModifierList, is FirCodeFragment -> {
val ktFile = psi?.containingFile as? KtFile val ktFile = psi?.containingFile as? KtFile
?: error("File for dangling modifier list cannot be null") ?: error("File for dangling modifier list cannot be null")
@@ -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.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirProvider 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.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.realPsi import org.jetbrains.kotlin.fir.realPsi
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider 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.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.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
@@ -174,26 +172,16 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
return candidate?.takeIf { it.psi == this } return candidate?.takeIf { it.psi == this }
} }
fun FirAnonymousInitializer.containingClass(): FirRegularClass { fun FirAnonymousInitializer.containingClassId(): ClassId {
val dispatchReceiverType = this.dispatchReceiverType val dispatchReceiverType = this.dispatchReceiverType
checkWithAttachment( checkWithAttachment(
condition = dispatchReceiverType != null, condition = dispatchReceiverType != null,
message = { "dispatchReceiverType for ${FirAnonymousInitializer::class.simpleName} modifier cannot be null" }, message = { "dispatchReceiverType for ${FirAnonymousInitializer::class.simpleName} modifier cannot be null" },
) { ) {
withFirEntry("initializer", this@containingClass) withFirEntry("initializer", this@containingClassId)
} }
val lookupTag = dispatchReceiverType.lookupTag return dispatchReceiverType.lookupTag.classId
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
} }
val ORIGINAL_DECLARATION_KEY = com.intellij.openapi.util.Key<KtDeclaration>("ORIGINAL_DECLARATION_KEY") val ORIGINAL_DECLARATION_KEY = com.intellij.openapi.util.Key<KtDeclaration>("ORIGINAL_DECLARATION_KEY")
@@ -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 {
<expr>init {
val i = 1
}</expr>
}
@@ -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<R|kotlin/Any|>
}
}
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<R|kotlin/Any|>
}
init {
[ResolvedTo(RAW_FIR)] lval i: R|kotlin/Int| = Int(1)
}
}
@@ -513,6 +513,12 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructuringEntry.kt"); 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 @Test
@TestMetadata("kt60387.kt") @TestMetadata("kt60387.kt")
public void testKt60387() throws Exception { public void testKt60387() throws Exception {
@@ -513,6 +513,12 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi
runTest("analysis/low-level-api-fir/testData/getOrBuildFir/declarations/destructuringEntry.kt"); 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 @Test
@TestMetadata("kt60387.kt") @TestMetadata("kt60387.kt")
public void testKt60387() throws Exception { public void testKt60387() throws Exception {