[LL FIR] add lazy resolve check to ensure that all nested declarations are resolved
This bow includes: value parameters, property accessors and class members; before, only class members was checked
This commit is contained in:
+5
-5
@@ -71,13 +71,13 @@ public inline fun buildErrorWithAttachment(
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
public inline fun checkWithAttachmentBuilder(
|
||||
value: Boolean,
|
||||
lazyMessage: () -> String,
|
||||
condition: Boolean,
|
||||
message: () -> String,
|
||||
buildAttachment: ExceptionAttachmentBuilder.() -> Unit = {}
|
||||
) {
|
||||
contract { returns() implies (value) }
|
||||
contract { returns() implies (condition) }
|
||||
|
||||
if (!value) {
|
||||
buildErrorWithAttachment(lazyMessage(), buildAttachment = buildAttachment)
|
||||
if (!condition) {
|
||||
buildErrorWithAttachment(message(), buildAttachment = buildAttachment)
|
||||
}
|
||||
}
|
||||
|
||||
+11
-10
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
@@ -61,7 +63,6 @@ internal class LLFirDesignatedAnnotationArgumentsResolveTransformer(
|
||||
|
||||
LLFirLazyTransformer.updatePhaseDeep(designation.declaration, FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
@@ -69,17 +70,17 @@ internal class LLFirDesignatedAnnotationArgumentsResolveTransformer(
|
||||
check(unresolvedAnnotation == null) {
|
||||
"Unexpected annotationTypeRef annotation, expected resolvedType but actual ${unresolvedAnnotation?.annotationTypeRef}"
|
||||
}
|
||||
when (declaration) {
|
||||
is FirSimpleFunction, is FirConstructor, is FirAnonymousInitializer ->
|
||||
declaration.checkPhase(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS)
|
||||
is FirProperty -> {
|
||||
declaration.checkPhase(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS)
|
||||
// declaration.getter?.ensurePhase(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS)
|
||||
// declaration.setter?.ensurePhase(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS)
|
||||
declaration.checkPhase(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS)
|
||||
|
||||
for (annotation in declaration.annotations) {
|
||||
for (argument in annotation.argumentMapping.mapping.values) {
|
||||
checkTypeRefIsResolved(argument.typeRef, "annotation argument", declaration) {
|
||||
withFirEntry("firAnnotation", annotation)
|
||||
withFirEntry("firArgument", argument)
|
||||
}
|
||||
}
|
||||
is FirClass, is FirTypeAlias, is FirEnumEntry, is FirField -> Unit
|
||||
else -> error("Unexpected type: ${declaration::class.simpleName}")
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-9
@@ -56,18 +56,12 @@ internal class LLFirDesignatedAnnotationsResolveTransformed(
|
||||
|
||||
LLFirLazyTransformer.updatePhaseDeep(designation.declaration, FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
when (declaration) {
|
||||
is FirClass, is FirTypeAlias ->
|
||||
declaration.checkPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
|
||||
is FirFunction, is FirProperty, is FirEnumEntry, is FirField, is FirAnonymousInitializer, is FirErrorProperty ->
|
||||
Unit
|
||||
else ->
|
||||
error("Unexpected type: ${declaration::class.simpleName}")
|
||||
}
|
||||
declaration.checkPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
|
||||
// todo add proper check that COMPILER_REQUIRED_ANNOTATIONS are resolved
|
||||
// checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-12
@@ -63,21 +63,11 @@ internal class LLFirDesignatedBodyResolveTransformer(
|
||||
ideDeclarationTransformer.ensureDesignationPassed()
|
||||
updatePhaseDeep(designation.declaration, FirResolvePhase.BODY_RESOLVE, withNonLocalDeclarations = true)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
when (declaration) {
|
||||
is FirSimpleFunction, is FirConstructor, is FirTypeAlias, is FirField, is FirAnonymousInitializer ->
|
||||
declaration.checkPhase(FirResolvePhase.BODY_RESOLVE)
|
||||
is FirProperty -> {
|
||||
declaration.checkPhase(FirResolvePhase.BODY_RESOLVE)
|
||||
// declaration.getter?.ensurePhase(FirResolvePhase.BODY_RESOLVE)
|
||||
// declaration.setter?.ensurePhase(FirResolvePhase.BODY_RESOLVE)
|
||||
}
|
||||
is FirEnumEntry, is FirClass -> Unit
|
||||
else -> error("Unexpected type: ${declaration::class.simpleName}")
|
||||
}
|
||||
declaration.checkPhase(FirResolvePhase.BODY_RESOLVE)
|
||||
checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-11
@@ -57,20 +57,13 @@ internal class LLFirDesignatedContractsResolveTransformer(
|
||||
ideDeclarationTransformer.ensureDesignationPassed()
|
||||
updatePhaseDeep(designation.declaration, FirResolvePhase.CONTRACTS)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
when (declaration) {
|
||||
is FirSimpleFunction, is FirConstructor, is FirAnonymousInitializer ->
|
||||
declaration.checkPhase(FirResolvePhase.CONTRACTS)
|
||||
is FirProperty -> {
|
||||
declaration.checkPhase(FirResolvePhase.CONTRACTS)
|
||||
// declaration.getter?.ensurePhase(FirResolvePhase.CONTRACTS)
|
||||
// declaration.setter?.ensurePhase(FirResolvePhase.CONTRACTS)
|
||||
}
|
||||
is FirClass, is FirTypeAlias, is FirEnumEntry, is FirField -> Unit
|
||||
else -> error("Unexpected type: ${declaration::class.simpleName}")
|
||||
declaration.checkPhase(FirResolvePhase.CONTRACTS)
|
||||
if (declaration is FirContractDescriptionOwner) {
|
||||
// TODO checkContractDescriptionIsResolved(declaration)
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-10
@@ -51,19 +51,12 @@ internal class LLFirDesignatedExpectActualMatcherTransformer(
|
||||
declarationTransformer.ensureDesignationPassed()
|
||||
updatePhaseDeep(designation.declaration, FirResolvePhase.EXPECT_ACTUAL_MATCHING)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
when (declaration) {
|
||||
is FirSimpleFunction, is FirConstructor, is FirAnonymousInitializer ->
|
||||
declaration.checkPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING)
|
||||
is FirProperty -> {
|
||||
declaration.checkPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING)
|
||||
}
|
||||
is FirClass, is FirTypeAlias, is FirEnumEntry, is FirField -> Unit
|
||||
else -> error("Unexpected type: ${declaration::class.simpleName}")
|
||||
}
|
||||
declaration.checkPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING)
|
||||
// TODO check if expect-actual matching is present
|
||||
checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -30,7 +30,6 @@ internal class LLFirDesignatedGeneratedCompanionObjectResolveTransformer(
|
||||
|
||||
LLFirLazyTransformer.updatePhaseDeep(designation.declaration, FirResolvePhase.COMPANION_GENERATION)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
|
||||
+6
-15
@@ -13,13 +13,13 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitAwa
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer.Companion.updatePhaseDeep
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkReturnTypeRefIsResolved
|
||||
|
||||
/**
|
||||
* Transform designation into IMPLICIT_TYPES_BODY_RESOLVE declaration. Affects only for target declaration, it's children and dependents
|
||||
@@ -54,7 +54,7 @@ internal class LLFirDesignatedImplicitTypesTransformer(
|
||||
if (designation.declaration.resolvePhase >= FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) return
|
||||
designation.declaration.checkPhase(FirResolvePhase.CONTRACTS)
|
||||
|
||||
ResolveTreeBuilder.resolvePhase(designation.declaration, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
|
||||
ResolveTreeBuilder.resolvePhase(designation.declaration, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
|
||||
phaseRunner.runPhaseWithCustomResolve(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
|
||||
designation.firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
@@ -63,22 +63,13 @@ internal class LLFirDesignatedImplicitTypesTransformer(
|
||||
ideDeclarationTransformer.ensureDesignationPassed()
|
||||
updatePhaseDeep(designation.declaration, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
when (declaration) {
|
||||
is FirSimpleFunction -> check(declaration.returnTypeRef is FirResolvedTypeRef)
|
||||
is FirField -> check(declaration.returnTypeRef is FirResolvedTypeRef)
|
||||
is FirClass, is FirConstructor, is FirTypeAlias, is FirEnumEntry, is FirAnonymousInitializer -> Unit
|
||||
is FirProperty -> {
|
||||
check(declaration.returnTypeRef is FirResolvedTypeRef)
|
||||
//Not resolved for some getters and setters #KT-46995
|
||||
// check(declaration.getter?.returnTypeRef?.let { it is FirResolvedTypeRef } ?: true)
|
||||
// check(declaration.setter?.returnTypeRef?.let { it is FirResolvedTypeRef } ?: true)
|
||||
// check(declaration.setter?.valueParameters?.get(0)?.returnTypeRef?.let { it is FirResolvedTypeRef } ?: true)
|
||||
}
|
||||
else -> error("Unexpected type: ${declaration::class.simpleName}")
|
||||
declaration.checkPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
|
||||
if (declaration is FirCallableDeclaration) {
|
||||
checkReturnTypeRefIsResolved(declaration)
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-15
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer.Companion.updatePhaseDeep
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDeclarationStatusIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
|
||||
/**
|
||||
@@ -50,27 +51,15 @@ internal class LLFirDesignatedStatusResolveTransformer(
|
||||
transformer.designationTransformer.ensureDesignationPassed()
|
||||
updatePhaseDeep(designation.declaration, FirResolvePhase.STATUS)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
if (declaration !is FirAnonymousInitializer) {
|
||||
declaration.checkPhase(FirResolvePhase.STATUS)
|
||||
}
|
||||
when (declaration) {
|
||||
is FirSimpleFunction -> check(declaration.status is FirResolvedDeclarationStatus)
|
||||
is FirConstructor -> check(declaration.status is FirResolvedDeclarationStatus)
|
||||
is FirTypeAlias -> check(declaration.status is FirResolvedDeclarationStatus)
|
||||
is FirEnumEntry -> check(declaration.status is FirResolvedDeclarationStatus)
|
||||
is FirField -> check(declaration.status is FirResolvedDeclarationStatus)
|
||||
is FirProperty -> {
|
||||
check(declaration.status is FirResolvedDeclarationStatus)
|
||||
check(declaration.getter?.status?.let { it is FirResolvedDeclarationStatus } ?: true)
|
||||
check(declaration.setter?.status?.let { it is FirResolvedDeclarationStatus } ?: true)
|
||||
}
|
||||
is FirRegularClass -> check(declaration.status is FirResolvedDeclarationStatus)
|
||||
is FirAnonymousInitializer -> Unit
|
||||
else -> error("Unexpected type: ${declaration::class.simpleName}")
|
||||
if (declaration is FirMemberDeclaration) {
|
||||
checkDeclarationStatusIsResolved(declaration)
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
+18
-16
@@ -5,14 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
|
||||
@@ -25,6 +17,14 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirResolvableS
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer.Companion.updatePhaseDeep
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
|
||||
/**
|
||||
* Transform designation into SUPER_TYPES phase. Affects only for designation, target declaration, it's children and dependents
|
||||
@@ -155,21 +155,23 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
|
||||
|
||||
updatePhaseDeep(designation.declaration, FirResolvePhase.SUPER_TYPES)
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
declaration.checkPhase(FirResolvePhase.SUPER_TYPES)
|
||||
when (declaration) {
|
||||
is FirFunction, is FirProperty, is FirEnumEntry, is FirField, is FirAnonymousInitializer -> Unit
|
||||
is FirRegularClass -> {
|
||||
declaration.checkPhase(FirResolvePhase.SUPER_TYPES)
|
||||
check(declaration.superTypeRefs.all { it is FirResolvedTypeRef })
|
||||
is FirClass -> {
|
||||
for (superTypeRef in declaration.superTypeRefs) {
|
||||
checkTypeRefIsResolved(superTypeRef, "class super type", declaration)
|
||||
}
|
||||
}
|
||||
|
||||
is FirTypeAlias -> {
|
||||
declaration.checkPhase(FirResolvePhase.SUPER_TYPES)
|
||||
check(declaration.expandedTypeRef is FirResolvedTypeRef)
|
||||
checkTypeRefIsResolved(declaration.expandedTypeRef, typeRefName = "type alias expanded type", declaration)
|
||||
}
|
||||
else -> error("Unexpected type: ${declaration::class.simpleName}")
|
||||
|
||||
else -> {}
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
+19
-28
@@ -5,19 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer.Companion.updatePhaseDeep
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.*
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTypeResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer.Companion.updatePhaseDeep
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
|
||||
|
||||
/**
|
||||
* Transform designation into TYPES phase. Affects only for designation, target declaration and it's children
|
||||
@@ -55,32 +52,26 @@ internal class LLFirDesignatedTypeResolverTransformer(
|
||||
updatePhaseDeep(designation.declaration, FirResolvePhase.TYPES)
|
||||
|
||||
checkIsResolved(designation.declaration)
|
||||
checkIsResolvedDeep(designation.declaration)
|
||||
checkClassMembersAreResolved(designation.declaration)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(declaration: FirDeclaration) {
|
||||
if (declaration !is FirAnonymousInitializer) {
|
||||
declaration.checkPhase(FirResolvePhase.TYPES)
|
||||
}
|
||||
declaration.checkPhase(FirResolvePhase.TYPES)
|
||||
when (declaration) {
|
||||
is FirFunction -> {
|
||||
check(declaration.returnTypeRef is FirResolvedTypeRef || declaration.returnTypeRef is FirImplicitTypeRef)
|
||||
check(declaration.receiverTypeRef?.let { it is FirResolvedTypeRef } ?: true)
|
||||
declaration.valueParameters.forEach {
|
||||
check(it.returnTypeRef is FirResolvedTypeRef || it.returnTypeRef is FirImplicitTypeRef)
|
||||
is FirCallableDeclaration -> {
|
||||
checkReturnTypeRefIsResolved(declaration, acceptImplicitTypeRef = true)
|
||||
checkReceiverTypeRefIsResolved(declaration)
|
||||
}
|
||||
|
||||
is FirTypeParameter -> {
|
||||
for (bound in declaration.bounds) {
|
||||
checkTypeRefIsResolved(bound, "type parameter bound", declaration)
|
||||
}
|
||||
}
|
||||
is FirProperty -> {
|
||||
check(declaration.returnTypeRef is FirResolvedTypeRef || declaration.returnTypeRef is FirImplicitTypeRef)
|
||||
check(declaration.receiverTypeRef?.let { it is FirResolvedTypeRef } ?: true)
|
||||
declaration.getter?.run(::checkIsResolved)
|
||||
declaration.setter?.run(::checkIsResolved)
|
||||
}
|
||||
is FirField -> check(declaration.returnTypeRef is FirResolvedTypeRef || declaration.returnTypeRef is FirImplicitTypeRef)
|
||||
is FirClass, is FirTypeAlias, is FirAnonymousInitializer -> Unit
|
||||
is FirEnumEntry -> check(declaration.returnTypeRef is FirResolvedTypeRef)
|
||||
is FirDiagnosticHolder -> {}
|
||||
else -> error("Unexpected type: ${declaration::class.simpleName}")
|
||||
|
||||
else -> {}
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(declaration)
|
||||
checkTypeParametersAreResolved(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
+40
-7
@@ -17,11 +17,44 @@ internal interface LLFirLazyTransformer {
|
||||
|
||||
fun checkIsResolved(declaration: FirDeclaration)
|
||||
|
||||
fun checkIsResolvedDeep(declaration: FirDeclaration) {
|
||||
if (!enableDeepEnsure) return
|
||||
checkIsResolved(declaration)
|
||||
if (declaration is FirRegularClass) {
|
||||
declaration.declarations.forEach(::checkIsResolvedDeep)
|
||||
fun checkNestedDeclarationsAreResolved(declaration: FirDeclaration) {
|
||||
checkFunctionParametersAreResolved(declaration)
|
||||
checkPropertyAccessorsAreResolved(declaration)
|
||||
checkClassMembersAreResolved(declaration)
|
||||
}
|
||||
|
||||
fun checkClassMembersAreResolved(declaration: FirDeclaration) {
|
||||
if (!needCheckingIfClassMembersAreResolved) return
|
||||
if (declaration is FirClass) {
|
||||
for (member in declaration.declarations) {
|
||||
checkClassMembersAreResolved(member)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkPropertyAccessorsAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirProperty) {
|
||||
declaration.getter?.let { checkIsResolved(it) }
|
||||
declaration.setter?.let { checkIsResolved(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun checkFunctionParametersAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirFunction) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
checkIsResolved(parameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkTypeParametersAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirTypeParameterRefsOwner) {
|
||||
for (parameter in declaration.typeParameters) {
|
||||
if (parameter is FirTypeParameter) {
|
||||
checkIsResolved(parameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +73,7 @@ internal interface LLFirLazyTransformer {
|
||||
if (element.resolvePhase >= newPhase) return
|
||||
element.replaceResolvePhase(newPhase)
|
||||
|
||||
if (element is FirCallableDeclaration) {
|
||||
if (element is FirTypeParameterRefsOwner) {
|
||||
element.typeParameters.forEach { typeParameter ->
|
||||
// if it is not a type parameter of outer declaration
|
||||
if (typeParameter is FirTypeParameter) {
|
||||
@@ -74,7 +107,7 @@ internal interface LLFirLazyTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
internal var enableDeepEnsure: Boolean = false
|
||||
internal var needCheckingIfClassMembersAreResolved: Boolean = false
|
||||
@TestOnly set
|
||||
|
||||
val DUMMY = object : LLFirLazyTransformer {
|
||||
|
||||
+1
@@ -26,6 +26,7 @@ fun ExceptionAttachmentBuilder.withFirEntry(name: String, fir: FirElement) {
|
||||
declarationRenderer = FirDeclarationRendererWithAttributes()
|
||||
).renderElementAsString(it)
|
||||
}
|
||||
withEntry("${name}FirSourceElementKind", fir.source?.kind?.let { it::class.simpleName })
|
||||
withPsiEntry("${name}Psi", fir.psi)
|
||||
}
|
||||
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.analysis.low.level.api.fir.util
|
||||
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.ExceptionAttachmentBuilder
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder
|
||||
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.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
internal inline fun checkTypeRefIsResolved(
|
||||
typeRef: FirTypeRef,
|
||||
typeRefName: String,
|
||||
owner: FirDeclaration,
|
||||
acceptImplicitTypeRef: Boolean = false,
|
||||
extraAttachment: ExceptionAttachmentBuilder.() -> Unit = {}
|
||||
) {
|
||||
checkWithAttachmentBuilder(
|
||||
condition = typeRef is FirResolvedTypeRef || acceptImplicitTypeRef && typeRef is FirImplicitTypeRef,
|
||||
message = {
|
||||
buildString {
|
||||
append("Expected ${FirResolvedTypeRef::class.simpleName}")
|
||||
if (acceptImplicitTypeRef) {
|
||||
append(" or ${FirImplicitTypeRef::class.simpleName}")
|
||||
}
|
||||
append(" for $typeRefName of ${owner::class.simpleName}(${owner.origin}) but ${typeRef::class.simpleName} found")
|
||||
}
|
||||
}
|
||||
) {
|
||||
withFirEntry("typeRef", typeRef)
|
||||
withFirEntry("firDeclaration", owner)
|
||||
extraAttachment()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkReturnTypeRefIsResolved(declaration: FirCallableDeclaration, acceptImplicitTypeRef: Boolean = false) {
|
||||
checkTypeRefIsResolved(declaration.returnTypeRef, typeRefName = "return type", declaration, acceptImplicitTypeRef)
|
||||
}
|
||||
|
||||
internal fun checkReceiverTypeRefIsResolved(declaration: FirCallableDeclaration, acceptImplicitTypeRef: Boolean = false) {
|
||||
val receiverTypeRef = declaration.receiverTypeRef ?: return
|
||||
checkTypeRefIsResolved(receiverTypeRef, typeRefName = "receiver type", declaration, acceptImplicitTypeRef)
|
||||
}
|
||||
|
||||
|
||||
internal fun checkContractDescriptionIsResolved(declaration: FirContractDescriptionOwner) {
|
||||
val contractDescription = declaration.contractDescription
|
||||
checkWithAttachmentBuilder(
|
||||
condition = contractDescription is FirResolvedContractDescription || contractDescription is FirEmptyContractDescription,
|
||||
message = { "Expected ${FirResolvedContractDescription::class.simpleName} or ${FirEmptyContractDescription::class.simpleName} but ${contractDescription::class.simpleName} found for ${declaration::class.simpleName}" }
|
||||
) {
|
||||
withFirEntry("declaration", declaration)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkDeclarationStatusIsResolved(declaration: FirMemberDeclaration) {
|
||||
val status = declaration.status
|
||||
checkWithAttachmentBuilder(
|
||||
condition = status is FirResolvedDeclarationStatus,
|
||||
message = { "Expected ${FirResolvedDeclarationStatus::class.simpleName} but ${declaration::class.simpleName} found for ${declaration::class.simpleName}" }
|
||||
) {
|
||||
withFirEntry("declaration", declaration)
|
||||
}
|
||||
}
|
||||
+11
-4
@@ -5,16 +5,22 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation
|
||||
|
||||
internal fun FirDeclaration.checkPhase(firResolvePhase: FirResolvePhase) =
|
||||
check(resolvePhase >= firResolvePhase) {
|
||||
"Element phase required to be $firResolvePhase but element resolved to $resolvePhase"
|
||||
internal fun FirDeclaration.checkPhase(requiredResolvePhase: FirResolvePhase) {
|
||||
val declarationResolvePhase = resolvePhase
|
||||
checkWithAttachmentBuilder(
|
||||
declarationResolvePhase >= requiredResolvePhase,
|
||||
{ "At least $requiredResolvePhase expected but $declarationResolvePhase found for ${this::class.simpleName}" }
|
||||
) {
|
||||
withFirEntry("firDeclaration", this@checkPhase)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun FirDeclarationDesignation.checkPathPhase(firResolvePhase: FirResolvePhase) =
|
||||
path.forEach { it.checkPhase(firResolvePhase) }
|
||||
@@ -23,6 +29,7 @@ internal fun FirDeclarationDesignation.checkDesignationPhase(firResolvePhase: Fi
|
||||
checkPathPhase(firResolvePhase)
|
||||
declaration.checkPhase(firResolvePhase)
|
||||
}
|
||||
|
||||
internal fun FirDeclarationDesignation.checkDesignationPhaseForClasses(firResolvePhase: FirResolvePhase) {
|
||||
checkPathPhase(firResolvePhase)
|
||||
if (declaration is FirClassLikeDeclaration) {
|
||||
|
||||
+3
-5
@@ -17,8 +17,6 @@ import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModulePr
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.TestInfrastructureInternals
|
||||
import org.jetbrains.kotlin.test.ExecutionListenerBasedDisposableProvider
|
||||
import org.jetbrains.kotlin.test.bind
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.builders.firHandlersStep
|
||||
import org.jetbrains.kotlin.test.builders.testConfiguration
|
||||
@@ -92,12 +90,12 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
|
||||
if (ignoreTest(filePath, configuration)) {
|
||||
return
|
||||
}
|
||||
val oldEnableDeepEnsure = LLFirLazyTransformer.enableDeepEnsure
|
||||
val oldEnableDeepEnsure = LLFirLazyTransformer.needCheckingIfClassMembersAreResolved
|
||||
try {
|
||||
LLFirLazyTransformer.enableDeepEnsure = true
|
||||
LLFirLazyTransformer.needCheckingIfClassMembersAreResolved = true
|
||||
super.runTest(filePath)
|
||||
} finally {
|
||||
LLFirLazyTransformer.enableDeepEnsure = oldEnableDeepEnsure
|
||||
LLFirLazyTransformer.needCheckingIfClassMembersAreResolved = oldEnableDeepEnsure
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user