FIR checkers: simplify hasVal / hasVar source element checks

This commit is contained in:
Mikhail Glukhikh
2020-11-19 15:29:29 +03:00
parent c6b703b598
commit 0838ab7fe7
2 changed files with 21 additions and 33 deletions
@@ -5,18 +5,11 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import com.intellij.lang.LighterASTNode
import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassKind.ANNOTATION_CLASS import org.jetbrains.kotlin.descriptors.ClassKind.ANNOTATION_CLASS
import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_CLASS import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_CLASS
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.FirLightSourceElement
import org.jetbrains.kotlin.fir.FirPsiSourceElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
@@ -27,10 +20,8 @@ import org.jetbrains.kotlin.fir.symbols.StandardClassIds.unsignedTypes
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.KtNodeTypes.FUN import org.jetbrains.kotlin.KtNodeTypes.FUN
import org.jetbrains.kotlin.KtNodeTypes.VALUE_PARAMETER import org.jetbrains.kotlin.KtNodeTypes.VALUE_PARAMETER
import org.jetbrains.kotlin.lexer.KtTokens.VAL_KEYWORD import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.lexer.KtTokens.VAR_KEYWORD
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtParameter
object FirAnnotationClassDeclarationChecker : FirBasicDeclarationChecker() { object FirAnnotationClassDeclarationChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -42,24 +33,11 @@ object FirAnnotationClassDeclarationChecker : FirBasicDeclarationChecker() {
when { when {
it is FirConstructor && it.isPrimary -> { it is FirConstructor && it.isPrimary -> {
for (parameter in it.valueParameters) { for (parameter in it.valueParameters) {
when (val parameterSourceElement = parameter.source) { val source = parameter.source ?: continue
is FirPsiSourceElement<*> -> { if (!source.hasValOrVar()) {
val parameterPsiElement = parameterSourceElement.psi as KtParameter reporter.report(source, FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER)
} else if (source.hasVar()) {
if (!parameterPsiElement.hasValOrVar()) reporter.report(source, FirErrors.VAR_ANNOTATION_PARAMETER)
reporter.report(parameterSourceElement, FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER)
else if (parameterPsiElement.isMutable)
reporter.report(parameterSourceElement, FirErrors.VAR_ANNOTATION_PARAMETER)
}
is FirLightSourceElement -> {
val kidsRef = Ref<Array<LighterASTNode?>>()
parameterSourceElement.treeStructure.getChildren(parameterSourceElement.lighterASTNode, kidsRef)
if (kidsRef.get().any { it?.tokenType == VAR_KEYWORD })
reporter.report(parameterSourceElement, FirErrors.VAR_ANNOTATION_PARAMETER)
else if (kidsRef.get().all { it?.tokenType != VAL_KEYWORD })
reporter.report(parameterSourceElement, FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER)
}
} }
val typeRef = parameter.returnTypeRef val typeRef = parameter.returnTypeRef
@@ -12,6 +12,7 @@ import com.intellij.psi.tree.IElementType
import com.intellij.psi.tree.TokenSet import com.intellij.psi.tree.TokenSet
import com.intellij.util.diff.FlyweightCapableTreeStructure 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.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
@@ -37,7 +38,7 @@ object LightTreePositioningStrategies {
val VAL_OR_VAR_NODE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() { val VAL_OR_VAR_NODE: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> { override fun mark(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): List<TextRange> {
val target = tree.findChildByType(node, VAL_VAR_TOKEN_SET) ?: node val target = tree.valOrVarKeyword(node) ?: node
return markElement(target, tree) return markElement(target, tree)
} }
} }
@@ -143,6 +144,12 @@ object LightTreePositioningStrategies {
} }
} }
fun FirSourceElement.hasValOrVar(): Boolean =
treeStructure.valOrVarKeyword(lighterASTNode) != null
fun FirSourceElement.hasVar(): Boolean =
treeStructure.findChildByType(lighterASTNode, KtTokens.VAR_KEYWORD) != null
private fun FlyweightCapableTreeStructure<LighterASTNode>.constructorKeyword(node: LighterASTNode): LighterASTNode? = private fun FlyweightCapableTreeStructure<LighterASTNode>.constructorKeyword(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.CONSTRUCTOR_KEYWORD) findChildByType(node, KtTokens.CONSTRUCTOR_KEYWORD)
@@ -158,6 +165,9 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.rightParenthesis(node:
private fun FlyweightCapableTreeStructure<LighterASTNode>.objectKeyword(node: LighterASTNode): LighterASTNode? = private fun FlyweightCapableTreeStructure<LighterASTNode>.objectKeyword(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.OBJECT_KEYWORD) findChildByType(node, KtTokens.OBJECT_KEYWORD)
private fun FlyweightCapableTreeStructure<LighterASTNode>.valOrVarKeyword(node: LighterASTNode): LighterASTNode? =
findChildByType(node, VAL_VAR_TOKEN_SET)
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)!!
@@ -186,15 +196,15 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.receiverTypeReference(
} }
private fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: IElementType): LighterASTNode? { private fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: IElementType): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode>>() val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef) getChildren(node, childrenRef)
return childrenRef.get()?.firstOrNull { it.tokenType == type } return childrenRef.get()?.firstOrNull { it?.tokenType == type }
} }
private fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: TokenSet): LighterASTNode? { private fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: TokenSet): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode>>() val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef) getChildren(node, childrenRef)
return childrenRef.get()?.firstOrNull { it.tokenType in type } return childrenRef.get()?.firstOrNull { it?.tokenType in type }
} }
private fun FlyweightCapableTreeStructure<LighterASTNode>.findParentOfType(node: LighterASTNode, type: IElementType): LighterASTNode? { private fun FlyweightCapableTreeStructure<LighterASTNode>.findParentOfType(node: LighterASTNode, type: IElementType): LighterASTNode? {