[K2] Refactor: extract conditions in FirExpectConsistencyChecker

...to separate methods.

After the change each diagnostic report has its own condition,
independent from others, so you don't have to keep in mind
"we're in else branch, so this is already not a FirConstructor
and also it either top-level or inside classs".
This makes changes in next commits more clear and verifiable.

`isTopLevelOrInsideClass` condition for
`getConstructorDelegationCall` is not needed, because
constructor is always inside class.

^KT-59899
This commit is contained in:
Roman Efremov
2023-09-14 17:22:37 +02:00
committed by Space Team
parent dda6d20520
commit 4404e5f036
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.hasBody import org.jetbrains.kotlin.fir.declarations.utils.hasBody
import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.visibility import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
// See old FE's [DeclarationsChecker] // See old FE's [DeclarationsChecker]
object FirExpectConsistencyChecker : FirBasicDeclarationChecker() { object FirExpectConsistencyChecker : FirBasicDeclarationChecker() {
@@ -24,7 +25,7 @@ object FirExpectConsistencyChecker : FirBasicDeclarationChecker() {
val isTopLevel = context.containingDeclarations.size == 1 val isTopLevel = context.containingDeclarations.size == 1
val lastClass = context.containingDeclarations.lastOrNull() as? FirClass val lastClass = context.containingDeclarations.lastOrNull() as? FirClass
val isInsideClass = lastClass != null val isTopLevelOrInsideClass = isTopLevel || lastClass != null
if (declaration is FirAnonymousInitializer) { if (declaration is FirAnonymousInitializer) {
if (lastClass?.isExpect == true) { if (lastClass?.isExpect == true) {
@@ -33,27 +34,41 @@ object FirExpectConsistencyChecker : FirBasicDeclarationChecker() {
return return
} }
if ( if (declaration !is FirMemberDeclaration || !declaration.isExpect) {
declaration !is FirMemberDeclaration ||
!isTopLevel && !isInsideClass ||
!declaration.isExpect
) {
return return
} }
if (declaration is FirConstructor) { getConstructorDelegationCall(declaration)?.let { delegatedConstructor ->
if (!declaration.isPrimary) { reporter.reportOn(delegatedConstructor.source, FirErrors.EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL, context)
val delegatedConstructorSource = declaration.delegatedConstructor?.source }
if (delegatedConstructorSource?.kind !is KtFakeSourceElementKind) {
reporter.reportOn(delegatedConstructorSource, FirErrors.EXPECTED_CLASS_CONSTRUCTOR_DELEGATION_CALL, context) if (isProhibitedPrivateDeclaration(declaration, isTopLevelOrInsideClass)) {
}
}
} else if (Visibilities.isPrivate(declaration.visibility)) {
reporter.reportOn(source, FirErrors.EXPECTED_PRIVATE_DECLARATION, context) reporter.reportOn(source, FirErrors.EXPECTED_PRIVATE_DECLARATION, context)
} }
if (declaration is FirFunction && declaration.hasBody) { if (isProhibitedDeclarationWithBody(declaration, isTopLevelOrInsideClass)) {
reporter.reportOn(source, FirErrors.EXPECTED_DECLARATION_WITH_BODY, context) reporter.reportOn(source, FirErrors.EXPECTED_DECLARATION_WITH_BODY, context)
} }
} }
private fun getConstructorDelegationCall(declaration: FirMemberDeclaration): FirDelegatedConstructorCall? {
if (declaration is FirConstructor) {
if (!declaration.isPrimary) {
val delegatedConstructor = declaration.delegatedConstructor
val delegatedConstructorSource = delegatedConstructor?.source
if (delegatedConstructorSource?.kind !is KtFakeSourceElementKind) {
return delegatedConstructor
}
}
}
return null
}
private fun isProhibitedPrivateDeclaration(declaration: FirMemberDeclaration, isTopLevelOrInsideClass: Boolean): Boolean {
return isTopLevelOrInsideClass && declaration !is FirConstructor && Visibilities.isPrivate(declaration.visibility)
}
private fun isProhibitedDeclarationWithBody(declaration: FirMemberDeclaration, isTopLevelOrInsideClass: Boolean): Boolean {
return isTopLevelOrInsideClass && declaration is FirFunction && declaration.hasBody
}
} }