diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt index 91b2be6654c..9595be3a068 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveT import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDelegatedConstructorIsResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkBodyIsResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDefaultValueIsResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkInitializerIsResolved @@ -50,6 +51,10 @@ internal object LLFirBodyLazyResolver : LLFirLazyResolver(FirResolvePhase.BODY_R when (target) { is FirValueParameter -> checkDefaultValueIsResolved(target) is FirVariable -> checkInitializerIsResolved(target) + is FirConstructor -> { + checkDelegatedConstructorIsResolved(target) + checkBodyIsResolved(target) + } is FirFunction -> checkBodyIsResolved(target) } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/firCheckResolvedUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/firCheckResolvedUtils.kt index 3b16f8ac5a0..015cfec7ed6 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/firCheckResolvedUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/firCheckResolvedUtils.kt @@ -13,9 +13,9 @@ import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall -import org.jetbrains.kotlin.fir.expressions.FirBlock -import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirResolvable import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList +import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef @@ -52,6 +52,33 @@ internal fun checkBodyIsResolved(function: FirFunction) { } } +internal fun checkDelegatedConstructorIsResolved(constructor: FirConstructor) { + val delegatedConstructorCall = constructor.delegatedConstructor ?: return + val calleeReference = delegatedConstructorCall.calleeReference + checkReferenceIsResolved(reference = calleeReference, owner = delegatedConstructorCall) { + withFirEntry("constructor", constructor) + } +} + +internal fun checkReferenceIsResolved( + reference: FirReference, + owner: FirResolvable, + extraAttachment: ExceptionAttachmentBuilder.() -> Unit = {}, +) { + checkWithAttachmentBuilder( + condition = reference is FirResolvedNamedReference || reference is FirErrorNamedReference || reference is FirFromMissingDependenciesNamedReference, + message = { + "Expected ${FirNamedReference::class.simpleName}, " + + "${FirErrorNamedReference::class.simpleName} " + + "or ${FirFromMissingDependenciesNamedReference::class.simpleName}, " + + "but ${reference::class.simpleName} found" + } + ) { + withFirEntry("referenceOwner", owner) + extraAttachment() + } +} + internal fun checkInitializerIsResolved(variable: FirVariable) { val initializer = variable.initializer ?: return checkTypeRefIsResolved(initializer.typeRef, "initializer type", variable) { diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/fakePrimaryConstructor.kt b/analysis/low-level-api-fir/testdata/lazyResolve/fakePrimaryConstructor.kt new file mode 100644 index 00000000000..420179d72bd --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/fakePrimaryConstructor.kt @@ -0,0 +1,7 @@ +// MEMBER_CLASS_FILTER: org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol + +class Problem { + fun foo(i: Int) { + + } +} diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/fakePrimaryConstructor.txt b/analysis/low-level-api-fir/testdata/lazyResolve/fakePrimaryConstructor.txt new file mode 100644 index 00000000000..24e47535063 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/fakePrimaryConstructor.txt @@ -0,0 +1,168 @@ +RAW_FIR: +FILE: [ResolvedTo(RAW_FIR)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(RAW_FIR)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +IMPORTS: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(RAW_FIR)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +COMPILER_REQUIRED_ANNOTATIONS: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(RAW_FIR)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +COMPANION_GENERATION: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(RAW_FIR)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(COMPANION_GENERATION)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +SUPER_TYPES: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(SUPER_TYPES)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(SUPER_TYPES)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +TYPES: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(TYPES)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(TYPES)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +STATUS: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +EXPECT_ACTUAL_MATCHING: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(EXPECT_ACTUAL_MATCHING)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +ARGUMENTS_OF_ANNOTATIONS: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +CONTRACTS: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(CONTRACTS)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +IMPLICIT_TYPES_BODY_RESOLVE: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +ANNOTATIONS_ARGUMENTS_MAPPING: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +BODY_RESOLVE: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +FILE RAW TO BODY: +FILE: [ResolvedTo(IMPORTS)] fakePrimaryConstructor.kt + [ResolvedTo(BODY_RESOLVE)] annotations container + public final [ResolvedTo(BODY_RESOLVE)] class Problem : R|kotlin/Any| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(BODY_RESOLVE)] fun foo([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/Int|): R|kotlin/Unit| { + } + + } diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/primaryConstructor.kt b/analysis/low-level-api-fir/testdata/lazyResolve/primaryConstructor.kt new file mode 100644 index 00000000000..569d1a8a16b --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/primaryConstructor.kt @@ -0,0 +1,5 @@ +class Problem constructor() { + fun foo(i: Int) { + + } +} diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/primaryConstructor.txt b/analysis/low-level-api-fir/testdata/lazyResolve/primaryConstructor.txt new file mode 100644 index 00000000000..3368b201e33 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/primaryConstructor.txt @@ -0,0 +1,168 @@ +RAW_FIR: +FILE: [ResolvedTo(RAW_FIR)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(RAW_FIR)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +IMPORTS: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(RAW_FIR)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(RAW_FIR)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +COMPILER_REQUIRED_ANNOTATIONS: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(RAW_FIR)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(COMPILER_REQUIRED_ANNOTATIONS)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +COMPANION_GENERATION: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(RAW_FIR)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(COMPANION_GENERATION)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +SUPER_TYPES: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(SUPER_TYPES)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(SUPER_TYPES)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +TYPES: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public? final? [ResolvedTo(TYPES)] class Problem : R|kotlin/Any| { + public? [ResolvedTo(TYPES)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public? final? [ResolvedTo(RAW_FIR)] fun foo([ResolvedTo(RAW_FIR)] i: Int): R|kotlin/Unit| { LAZY_BLOCK } + + } + +STATUS: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +EXPECT_ACTUAL_MATCHING: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(EXPECT_ACTUAL_MATCHING)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +ARGUMENTS_OF_ANNOTATIONS: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] [ContainingClassKey=Problem] constructor(): R|Problem| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +CONTRACTS: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(CONTRACTS)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +IMPLICIT_TYPES_BODY_RESOLVE: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(IMPLICIT_TYPES_BODY_RESOLVE)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +ANNOTATIONS_ARGUMENTS_MAPPING: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +BODY_RESOLVE: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(RAW_FIR)] annotations container + public final [ResolvedTo(STATUS)] class Problem : R|kotlin/Any| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(STATUS)] fun foo([ResolvedTo(STATUS)] i: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + + } + +FILE RAW TO BODY: +FILE: [ResolvedTo(IMPORTS)] primaryConstructor.kt + [ResolvedTo(BODY_RESOLVE)] annotations container + public final [ResolvedTo(BODY_RESOLVE)] class Problem : R|kotlin/Any| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=Problem] constructor(): R|Problem| { + super() + } + + public final [ResolvedTo(BODY_RESOLVE)] fun foo([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/Int|): R|kotlin/Unit| { + } + + } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveTest.kt index 023f86ce042..f9255d3b0af 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveTest.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveTest.kt @@ -10,26 +10,26 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLeve import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirOutOfContentRootTestConfigurator import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider -import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirResolvePhase -import org.jetbrains.kotlin.fir.realPsi import org.jetbrains.kotlin.fir.renderer.FirDeclarationRendererWithAttributes import org.jetbrains.kotlin.fir.renderer.FirErrorExpressionExtendedRenderer import org.jetbrains.kotlin.fir.renderer.FirFileAnnotationsContainerRenderer import org.jetbrains.kotlin.fir.renderer.FirRenderer import org.jetbrains.kotlin.fir.renderer.FirResolvePhaseRenderer +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase -import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.directives.ConfigurationDirectives +import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer +import org.jetbrains.kotlin.test.directives.model.ValueDirective +import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue import org.jetbrains.kotlin.test.services.TestModuleStructure import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.assertions -import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeAsciiOnly import org.junit.jupiter.api.parallel.Execution import org.junit.jupiter.api.parallel.ExecutionMode @@ -51,7 +51,8 @@ abstract class AbstractFirLazyDeclarationResolveTest : AbstractLowLevelApiSingle resolveWithClearCaches(ktFile) { firResolveSession -> check(firResolveSession.isSourceSession) val ktDeclaration = testServices.expressionMarkerProvider.getElementOfTypeAtCaret(ktFile) - val declarationToResolve = ktDeclaration.resolveToFirSymbol(firResolveSession) + val declarationSymbol = ktDeclaration.resolveToFirSymbol(firResolveSession) + val declarationToResolve = chooseMemberDeclarationIfNeeded(declarationSymbol, moduleStructure) for (currentPhase in FirResolvePhase.values()) { if (currentPhase == FirResolvePhase.SEALED_CLASS_INHERITORS) continue @@ -82,12 +83,32 @@ abstract class AbstractFirLazyDeclarationResolveTest : AbstractLowLevelApiSingle testServices.assertions.assertEqualsToTestDataFileSibling(resultBuilder.toString()) } + private fun chooseMemberDeclarationIfNeeded(symbol: FirBasedSymbol<*>, moduleStructure: TestModuleStructure): FirBasedSymbol<*> { + val memberClassFilter = moduleStructure.allDirectives.singleOrZeroValue(Directives.MEMBER_CLASS_FILTER) ?: return symbol + val classSymbol = symbol as FirClassSymbol + val declarations = classSymbol.declarationSymbols + val filteredSymbols = declarations.filter { memberClassFilter.isInstance(it) } + return when (filteredSymbols.size) { + 0 -> error("Empty result for:${declarations.joinToString("\n")}") + 1 -> filteredSymbols.single() + else -> error("Result ambiguity:\n${filteredSymbols.joinToString("\n")}") + } + } + override fun configureTest(builder: TestConfigurationBuilder) { super.configureTest(builder) with(builder) { defaultDirectives { +ConfigurationDirectives.WITH_STDLIB } + + useDirectives(Directives) + } + } + + private object Directives : SimpleDirectivesContainer() { + val MEMBER_CLASS_FILTER: ValueDirective> by valueDirective("Choose member declaration by a declaration class") { + Class.forName(it) } } } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java index 33edf696faa..ef1d2c2808b 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java @@ -102,6 +102,12 @@ public class FirOutOfContentRootLazyDeclarationResolveTestGenerated extends Abst runTest("analysis/low-level-api-fir/testdata/lazyResolve/fakeOverride.kt"); } + @Test + @TestMetadata("fakePrimaryConstructor.kt") + public void testFakePrimaryConstructor() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/fakePrimaryConstructor.kt"); + } + @Test @TestMetadata("functionWithParameter.kt") public void testFunctionWithParameter() throws Exception { @@ -126,6 +132,12 @@ public class FirOutOfContentRootLazyDeclarationResolveTestGenerated extends Abst runTest("analysis/low-level-api-fir/testdata/lazyResolve/parameterOfTopSetter.kt"); } + @Test + @TestMetadata("primaryConstructor.kt") + public void testPrimaryConstructor() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/primaryConstructor.kt"); + } + @Test @TestMetadata("primaryConstructorParameter.kt") public void testPrimaryConstructorParameter() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java index 4542744551b..3e8ba487f56 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java @@ -102,6 +102,12 @@ public class FirSourceLazyDeclarationResolveTestGenerated extends AbstractFirSou runTest("analysis/low-level-api-fir/testdata/lazyResolve/fakeOverride.kt"); } + @Test + @TestMetadata("fakePrimaryConstructor.kt") + public void testFakePrimaryConstructor() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/fakePrimaryConstructor.kt"); + } + @Test @TestMetadata("functionWithParameter.kt") public void testFunctionWithParameter() throws Exception { @@ -126,6 +132,12 @@ public class FirSourceLazyDeclarationResolveTestGenerated extends AbstractFirSou runTest("analysis/low-level-api-fir/testdata/lazyResolve/parameterOfTopSetter.kt"); } + @Test + @TestMetadata("primaryConstructor.kt") + public void testPrimaryConstructor() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/primaryConstructor.kt"); + } + @Test @TestMetadata("primaryConstructorParameter.kt") public void testPrimaryConstructorParameter() throws Exception {