From 7d31ea3e8ffb71edc142935749172b31bc836a54 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Tue, 16 Mar 2021 09:54:07 +0000 Subject: [PATCH] FIR checker: Add utility functions for FirModifierList. --- .../declaration/FirConstPropertyChecker.kt | 4 +-- .../FirConstructorAllowedChecker.kt | 2 +- .../declaration/FirDeclarationCheckerUtils.kt | 5 ++- .../FirInlineClassDeclarationChecker.kt | 3 +- .../declaration/FirMemberFunctionsChecker.kt | 6 ++-- .../declaration/FirMemberPropertiesChecker.kt | 6 ++-- .../declaration/FirModifierChecker.kt | 2 +- .../checkers/declaration/FirModifierUtils.kt | 35 ++++++++++++------- .../declaration/FirOpenMemberChecker.kt | 4 +-- .../FirTopLevelFunctionsChecker.kt | 3 +- .../FirTopLevelPropertiesChecker.kt | 2 +- .../jvm/FirJvmExternalDeclarationChecker.kt | 5 +-- 12 files changed, 40 insertions(+), 37 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstPropertyChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstPropertyChecker.kt index 5b8aba12b73..130b10113b2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstPropertyChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstPropertyChecker.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirModifierList.Companion.getModifierList import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn @@ -21,8 +20,7 @@ object FirConstPropertyChecker : FirPropertyChecker() { if (!declaration.isConst) return if (declaration.isVar) { - val modifierList = with(FirModifierList) { declaration.source.getModifierList() } - val constModifier = modifierList?.modifiers?.firstOrNull { it.token == KtTokens.CONST_KEYWORD } + val constModifier = declaration.getModifier(KtTokens.CONST_KEYWORD) constModifier?.let { reporter.reportOn(it.source, FirErrors.WRONG_MODIFIER_TARGET, it.token, "vars", context) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstructorAllowedChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstructorAllowedChecker.kt index f850ffcfbaa..dcac87d497f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstructorAllowedChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstructorAllowedChecker.kt @@ -32,7 +32,7 @@ object FirConstructorAllowedChecker : FirConstructorChecker() { reporter.reportOn(source, FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM, context) } ClassKind.CLASS -> if (containingClass is FirRegularClass && containingClass.modality == Modality.SEALED) { - val modifierList = with(FirModifierList) { source.getModifierList() } ?: return + val modifierList = source.getModifierList() ?: return val hasIllegalModifier = modifierList.modifiers.any { it.token != KtTokens.PROTECTED_KEYWORD && it.token != KtTokens.PRIVATE_KEYWORD } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt index 5a6ed8b3bfa..d1b0855e155 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDeclarationCheckerUtils.kt @@ -85,7 +85,7 @@ internal fun checkPropertyInitializer( context: CheckerContext ) { val inInterface = containingClass?.isInterface == true - val hasAbstractModifier = modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true + val hasAbstractModifier = KtTokens.ABSTRACT_KEYWORD in modifierList val isAbstract = property.isAbstract || hasAbstractModifier if (isAbstract) { if (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) { @@ -184,6 +184,5 @@ internal val FirClass<*>.canHaveOpenMembers: Boolean get() = modality() != Modal internal fun FirRegularClass.isInlineOrValueClass(): Boolean { if (this.classKind != ClassKind.CLASS) return false - val modifierList = with(FirModifierList) { source.getModifierList() } - return isInline || modifierList?.modifiers?.any { it.token == KtTokens.VALUE_KEYWORD } == true + return isInline || hasModifier(KtTokens.VALUE_KEYWORD) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineClassDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineClassDeclarationChecker.kt index f2341cf7970..252cfd50b36 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineClassDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInlineClassDeclarationChecker.kt @@ -173,8 +173,7 @@ object FirInlineClassDeclarationChecker : FirRegularClassChecker() { private fun FirValueParameter.isNotFinalReadOnly(primaryConstructorProperty: FirProperty?): Boolean { if (primaryConstructorProperty == null) return true - val modifierList = with(FirModifierList) { source.getModifierList() } - val isOpen = modifierList?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true + val isOpen = hasModifier(KtTokens.OPEN_KEYWORD) return isVararg || !primaryConstructorProperty.isVal || isOpen } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberFunctionsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberFunctionsChecker.kt index e54e06d5939..e603383bf44 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberFunctionsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberFunctionsChecker.kt @@ -34,8 +34,8 @@ object FirMemberFunctionsChecker : FirRegularClassChecker() { if (source.kind is FirFakeSourceElementKind) return // If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`. // So, our source of truth should be the full modifier list retrieved from the source. - val modifierList = with(FirModifierList) { source.getModifierList() } - val hasAbstractModifier = modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true + val modifierList = source.getModifierList() + val hasAbstractModifier = KtTokens.ABSTRACT_KEYWORD in modifierList val isAbstract = function.isAbstract || hasAbstractModifier if (isAbstract) { if (!containingDeclaration.canHaveAbstractDeclaration) { @@ -49,7 +49,7 @@ object FirMemberFunctionsChecker : FirRegularClassChecker() { } } val isInsideExpectClass = isInsideExpectClass(containingDeclaration, context) - val hasOpenModifier = modifierList?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true + val hasOpenModifier = KtTokens.OPEN_KEYWORD in modifierList if (!function.hasBody) { if (containingDeclaration.isInterface) { if (Visibilities.isPrivate(function.visibility)) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt index aefc9b9b98c..3fd50167b89 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirMemberPropertiesChecker.kt @@ -146,7 +146,7 @@ object FirMemberPropertiesChecker : FirRegularClassChecker() { if (source.kind is FirFakeSourceElementKind) return // If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`. // So, our source of truth should be the full modifier list retrieved from the source. - val modifierList = with(FirModifierList) { property.source.getModifierList() } + val modifierList = property.source.getModifierList() checkPropertyInitializer( containingDeclaration, @@ -159,7 +159,7 @@ object FirMemberPropertiesChecker : FirRegularClassChecker() { checkPropertyAccessors(property, reporter, context) checkExpectDeclarationVisibilityAndBody(property, source, reporter, context) - val hasAbstractModifier = modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true + val hasAbstractModifier = KtTokens.ABSTRACT_KEYWORD in modifierList val isAbstract = property.isAbstract || hasAbstractModifier if (containingDeclaration.isInterface && Visibilities.isPrivate(property.visibility) && @@ -203,7 +203,7 @@ object FirMemberPropertiesChecker : FirRegularClassChecker() { } } - val hasOpenModifier = modifierList?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true + val hasOpenModifier = KtTokens.OPEN_KEYWORD in modifierList if (hasOpenModifier && containingDeclaration.isInterface && !hasAbstractModifier && diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt index 95140abcea0..1a3f0e4c1c8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt @@ -169,7 +169,7 @@ object FirModifierChecker : FirBasicDeclarationChecker() { if (!isDeclarationMappedToSourceCorrectly(declaration, source)) return if (context.containingDeclarations.last() is FirDefaultPropertyAccessor) return - val modifierList = with(FirModifierList) { source.getModifierList() } + val modifierList = source.getModifierList() modifierList?.let { checkModifiers(it, declaration, reporter, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierUtils.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierUtils.kt index 2aed20a46d7..7615899158a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierUtils.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierUtils.kt @@ -12,6 +12,7 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.checkers.getChildren +import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtModifierList @@ -44,19 +45,9 @@ internal sealed class FirModifierList { } } - companion object { - fun FirSourceElement?.getModifierList(): FirModifierList? { - return when (this) { - null -> null - is FirPsiSourceElement<*> -> (psi as? KtModifierListOwner)?.modifierList?.let { FirPsiModifierList(it) } - is FirLightSourceElement -> { - val modifierListNode = lighterASTNode.getChildren(treeStructure).find { it?.tokenType == KtNodeTypes.MODIFIER_LIST } - ?: return null - FirLightModifierList(modifierListNode, treeStructure) - } - } - } - } + operator fun get(token: KtModifierKeywordToken): FirModifier<*>? = modifiers.firstOrNull { it.token == token } + + operator fun contains(token: KtModifierKeywordToken): Boolean = modifiers.any { it.token == token } } private val MODIFIER_KEYWORD_SET = TokenSet.orSet(KtTokens.SOFT_KEYWORDS, TokenSet.create(KtTokens.IN_KEYWORD, KtTokens.FUN_KEYWORD)) @@ -82,3 +73,21 @@ internal sealed class FirModifier(val node: Node, val token: KtModif abstract val source: FirSourceElement } + +internal fun FirSourceElement?.getModifierList(): FirModifierList? { + return when (this) { + null -> null + is FirPsiSourceElement<*> -> (psi as? KtModifierListOwner)?.modifierList?.let { FirModifierList.FirPsiModifierList(it) } + is FirLightSourceElement -> { + val modifierListNode = lighterASTNode.getChildren(treeStructure).find { it?.tokenType == KtNodeTypes.MODIFIER_LIST } + ?: return null + FirModifierList.FirLightModifierList(modifierListNode, treeStructure) + } + } +} + +internal operator fun FirModifierList?.contains(token: KtModifierKeywordToken): Boolean = this?.contains(token) == true + +internal fun FirDeclaration.getModifier(token: KtModifierKeywordToken): FirModifier<*>? = source.getModifierList()?.get(token) + +internal fun FirDeclaration.hasModifier(token: KtModifierKeywordToken): Boolean = token in source.getModifierList() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOpenMemberChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOpenMemberChecker.kt index 715c3871fd0..0d32322d13d 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOpenMemberChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOpenMemberChecker.kt @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirRealSourceElementKind import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext -import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirModifierList.Companion.getModifierList import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn @@ -29,7 +28,7 @@ object FirOpenMemberChecker : FirClassChecker() { memberDeclaration is FirConstructor ) continue val source = memberDeclaration.source ?: continue - if (memberDeclaration.isOpen || (source.hasOpenModifierInSource && source.shouldReportOpenFromSource)) { + if (memberDeclaration.isOpen || memberDeclaration.hasModifier(KtTokens.OPEN_KEYWORD) && source.shouldReportOpenFromSource) { if (declaration.classKind == ClassKind.OBJECT) { reporter.reportOn(source, FirErrors.NON_FINAL_MEMBER_IN_OBJECT, context) } else { @@ -39,7 +38,6 @@ object FirOpenMemberChecker : FirClassChecker() { } } - private val FirSourceElement.hasOpenModifierInSource: Boolean get() = getModifierList()?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true private val FirSourceElement.shouldReportOpenFromSource: Boolean get() = when (kind) { FirRealSourceElementKind, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelFunctionsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelFunctionsChecker.kt index fc1f0ffec2c..3e7577381be 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelFunctionsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelFunctionsChecker.kt @@ -28,8 +28,7 @@ object FirTopLevelFunctionsChecker : FirFileChecker() { if (source.kind is FirFakeSourceElementKind) return // If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`. // So, our source of truth should be the full modifier list retrieved from the source. - val modifierList = with(FirModifierList) { source.getModifierList() } - if (modifierList?.modifiers?.any { it.token == KtTokens.ABSTRACT_KEYWORD } == true) return + if (function.hasModifier(KtTokens.ABSTRACT_KEYWORD)) return if (function.isExternal) return if (!function.hasBody && !function.isExpect) { reporter.reportOn(source, FirErrors.NON_MEMBER_FUNCTION_NO_BODY, function, context) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt index 6f5904ca585..fe82430aec1 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt @@ -26,7 +26,7 @@ object FirTopLevelPropertiesChecker : FirFileChecker() { if (source.kind is FirFakeSourceElementKind) return // If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`. // So, our source of truth should be the full modifier list retrieved from the source. - val modifierList = with(FirModifierList) { source.getModifierList() } + val modifierList = source.getModifierList() checkPropertyInitializer( containingClass = null, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/jvm/FirJvmExternalDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/jvm/FirJvmExternalDeclarationChecker.kt index 62e107f16dc..77531f3e6b0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/jvm/FirJvmExternalDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/jvm/FirJvmExternalDeclarationChecker.kt @@ -9,6 +9,8 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirModifierList +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.getModifier +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.getModifierList import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn @@ -29,8 +31,7 @@ object FirJvmExternalDeclarationChecker : FirMemberDeclarationChecker() { is FirRegularClass -> "class" else -> "non-function declaration" } - val modifierList = with(FirModifierList) { source.getModifierList() } - val externalModifier = modifierList?.modifiers?.firstOrNull { it.token == KtTokens.EXTERNAL_KEYWORD } + val externalModifier = declaration.getModifier(KtTokens.EXTERNAL_KEYWORD) externalModifier?.let { reporter.reportOn(it.source, FirErrors.WRONG_MODIFIER_TARGET, it.token, target, context) }