[FIR] Introduce & use MODALITY_MODIFIER positioning strategy

This commit is contained in:
Mikhail Glukhikh
2020-11-25 13:51:22 +03:00
parent 54f9edb597
commit 5fbdc0af5e
5 changed files with 33 additions and 14 deletions
@@ -11,17 +11,17 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext 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.FirMemberDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.implicitModality import org.jetbrains.kotlin.fir.analysis.checkers.implicitModality
import org.jetbrains.kotlin.fir.analysis.checkers.toToken
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER
import org.jetbrains.kotlin.fir.analysis.getChild import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.modality import org.jetbrains.kotlin.fir.declarations.modality
object RedundantModalityModifierChecker : FirMemberDeclarationChecker() { object RedundantModalityModifierChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration.source?.kind is FirFakeSourceElementKind) return val source = declaration.source
if (source?.kind is FirFakeSourceElementKind) return
val modality = declaration.modality ?: return val modality = declaration.modality ?: return
if ( if (
@@ -29,11 +29,10 @@ object RedundantModalityModifierChecker : FirMemberDeclarationChecker() {
&& (context.containingDeclarations.last() as? FirClass<*>)?.classKind == ClassKind.INTERFACE && (context.containingDeclarations.last() as? FirClass<*>)?.classKind == ClassKind.INTERFACE
) return ) return
if (source != null && source.treeStructure.modalityModifier(source.lighterASTNode) == null) return
val implicitModality = declaration.implicitModality(context) val implicitModality = declaration.implicitModality(context)
if (modality != implicitModality) return if (modality != implicitModality) return
val modalityModifierSource = declaration.source?.getChild(modality.toToken(), depth = 2) reporter.report(source, REDUNDANT_MODALITY_MODIFIER)
reporter.report(modalityModifierSource, REDUNDANT_MODALITY_MODIFIER)
} }
} }
@@ -155,7 +155,7 @@ object FirErrors {
// Extended checkers group // Extended checkers group
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, PsiElement>() val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
val REDUNDANT_RETURN_UNIT_TYPE by warning0<FirSourceElement, PsiTypeElement>() val REDUNDANT_RETURN_UNIT_TYPE by warning0<FirSourceElement, PsiTypeElement>()
val REDUNDANT_EXPLICIT_TYPE by warning0<FirSourceElement, PsiElement>() val REDUNDANT_EXPLICIT_TYPE by warning0<FirSourceElement, PsiElement>()
val REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE by warning0<FirSourceElement, PsiElement>() val REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE by warning0<FirSourceElement, PsiElement>()
@@ -14,6 +14,8 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.MODALITY_MODIFIERS
import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
object LightTreePositioningStrategies { object LightTreePositioningStrategies {
@@ -143,9 +145,9 @@ object LightTreePositioningStrategies {
} }
} }
val VISIBILITY_MODIFIER: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { private class ModifierSetBasedLightTreePositioningStrategy(private val modifierSet: TokenSet) : LightTreePositioningStrategy() {
override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> { override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> {
tree.visibilityModifier(node)?.let { return markElement(it, tree) } tree.findChildByType(node, modifierSet)?.let { return markElement(it, tree) }
tree.nameIdentifier(node)?.let { return markElement(it, tree) } tree.nameIdentifier(node)?.let { return markElement(it, tree) }
return when (node.tokenType) { return when (node.tokenType) {
KtNodeTypes.OBJECT_DECLARATION -> { KtNodeTypes.OBJECT_DECLARATION -> {
@@ -159,6 +161,10 @@ object LightTreePositioningStrategies {
} }
} }
val VISIBILITY_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(VISIBILITY_MODIFIERS)
val MODALITY_MODIFIER: LightTreePositioningStrategy = ModifierSetBasedLightTreePositioningStrategy(MODALITY_MODIFIERS)
val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { val OPERATOR: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> { override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> {
return markElement(tree.operationReference(node) ?: node, tree) return markElement(tree.operationReference(node) ?: node, tree)
@@ -196,8 +202,11 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.objectKeyword(node: Li
private fun FlyweightCapableTreeStructure<LighterASTNode>.valOrVarKeyword(node: LighterASTNode): LighterASTNode? = private fun FlyweightCapableTreeStructure<LighterASTNode>.valOrVarKeyword(node: LighterASTNode): LighterASTNode? =
findChildByType(node, VAL_VAR_TOKEN_SET) findChildByType(node, VAL_VAR_TOKEN_SET)
private fun FlyweightCapableTreeStructure<LighterASTNode>.visibilityModifier(node: LighterASTNode): LighterASTNode? = internal fun FlyweightCapableTreeStructure<LighterASTNode>.visibilityModifier(declaration: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.VISIBILITY_MODIFIERS) modifierList(declaration)?.let { findChildByType(it, VISIBILITY_MODIFIERS) }
internal fun FlyweightCapableTreeStructure<LighterASTNode>.modalityModifier(declaration: LighterASTNode): LighterASTNode? =
modifierList(declaration)?.let { findChildByType(it, MODALITY_MODIFIERS) }
private fun FlyweightCapableTreeStructure<LighterASTNode>.accessorNamePlaceholder(node: LighterASTNode): LighterASTNode = private fun FlyweightCapableTreeStructure<LighterASTNode>.accessorNamePlaceholder(node: LighterASTNode): LighterASTNode =
findChildByType(node, KtTokens.GET_KEYWORD) ?: findChildByType(node, KtTokens.SET_KEYWORD)!! findChildByType(node, KtTokens.GET_KEYWORD) ?: findChildByType(node, KtTokens.SET_KEYWORD)!!
@@ -38,6 +38,11 @@ object SourceElementPositioningStrategies {
PositioningStrategies.VISIBILITY_MODIFIER PositioningStrategies.VISIBILITY_MODIFIER
) )
val MODALITY_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.MODALITY_MODIFIER,
PositioningStrategies.MODALITY_MODIFIER
)
val OPERATOR = SourceElementPositioningStrategy( val OPERATOR = SourceElementPositioningStrategy(
LightTreePositioningStrategies.OPERATOR, LightTreePositioningStrategies.OPERATOR,
PositioningStrategies.OPERATOR PositioningStrategies.OPERATOR
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.diagnostics.Errors.ACTUAL_WITHOUT_EXPECT
import org.jetbrains.kotlin.diagnostics.Errors.NO_ACTUAL_FOR_EXPECT import org.jetbrains.kotlin.diagnostics.Errors.NO_ACTUAL_FOR_EXPECT
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.MODALITY_MODIFIERS
import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS import org.jetbrains.kotlin.lexer.KtTokens.VISIBILITY_MODIFIERS
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.psi.psiUtil.*
@@ -403,12 +404,11 @@ object PositioningStrategies {
} }
} }
@JvmField private class ModifierSetBasedPositioningStrategy(private val modifierSet: TokenSet) : PositioningStrategy<KtModifierListOwner>() {
val VISIBILITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = object : PositioningStrategy<KtModifierListOwner>() {
override fun mark(element: KtModifierListOwner): List<TextRange> { override fun mark(element: KtModifierListOwner): List<TextRange> {
val modifierList = element.modifierList val modifierList = element.modifierList
val result = VISIBILITY_MODIFIERS.types.mapNotNull { modifierList?.getModifier(it as KtModifierKeywordToken)?.textRange } val result = modifierSet.types.mapNotNull { modifierList?.getModifier(it as KtModifierKeywordToken)?.textRange }
if (result.isNotEmpty()) return result if (result.isNotEmpty()) return result
// Try to resolve situation when there's no visibility modifiers written before element // Try to resolve situation when there's no visibility modifiers written before element
@@ -431,6 +431,12 @@ object PositioningStrategies {
} }
} }
@JvmField
val VISIBILITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = ModifierSetBasedPositioningStrategy(VISIBILITY_MODIFIERS)
@JvmField
val MODALITY_MODIFIER: PositioningStrategy<KtModifierListOwner> = ModifierSetBasedPositioningStrategy(MODALITY_MODIFIERS)
@JvmField @JvmField
val VARIANCE_IN_PROJECTION: PositioningStrategy<KtTypeProjection> = object : PositioningStrategy<KtTypeProjection>() { val VARIANCE_IN_PROJECTION: PositioningStrategy<KtTypeProjection> = object : PositioningStrategy<KtTypeProjection>() {
override fun mark(element: KtTypeProjection): List<TextRange> { override fun mark(element: KtTypeProjection): List<TextRange> {