FIR: introduce & use SELECTOR_BY_QUALIFIED positioning strategy

This commit is contained in:
Mikhail Glukhikh
2021-02-17 16:26:17 +03:00
parent 5892646a27
commit 5ca3ce9e37
6 changed files with 60 additions and 6 deletions
@@ -42,6 +42,7 @@ enum class PositioningStrategy(private val strategy: String) {
IF_EXPRESSION("IF_EXPRESSION"),
VARIANCE_MODIFIER("VARIANCE_MODIFIER"),
LATEINIT_MODIFIER("LATEINIT_MODIFIER"),
SELECTOR_BY_QUALIFIED("SELECTOR_BY_QUALIFIED"),
;
@@ -388,7 +388,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
val FUNCTION_CONTRACTS by object : DiagnosticGroup("Function contracts") {
val ERROR_IN_CONTRACT_DESCRIPTION by error<FirSourceElement, KtElement> {
val ERROR_IN_CONTRACT_DESCRIPTION by error<FirSourceElement, KtElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<String>("reason")
}
}
@@ -401,7 +401,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE by warning<FirSourceElement, PsiElement>()
val CAN_BE_VAL by warning<FirSourceElement, KtDeclaration>(PositioningStrategy.VAL_OR_VAR_NODE)
val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning<FirSourceElement, KtExpression>(PositioningStrategy.OPERATOR)
val REDUNDANT_CALL_OF_CONVERSION_METHOD by warning<FirSourceElement, PsiElement>()
val REDUNDANT_CALL_OF_CONVERSION_METHOD by warning<FirSourceElement, PsiElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
val ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS by warning<FirSourceElement, KtExpression>(PositioningStrategy.OPERATOR)
val EMPTY_RANGE by warning<FirSourceElement, PsiElement>()
val REDUNDANT_SETTER_PARAMETER_TYPE by warning<FirSourceElement, PsiElement>()
@@ -409,7 +409,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val ASSIGNED_VALUE_IS_NEVER_READ by warning<FirSourceElement, PsiElement>()
val VARIABLE_INITIALIZER_IS_REDUNDANT by warning<FirSourceElement, PsiElement>()
val VARIABLE_NEVER_READ by warning<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
val USELESS_CALL_ON_NOT_NULL by warning<FirSourceElement, PsiElement>()
val USELESS_CALL_ON_NOT_NULL by warning<FirSourceElement, PsiElement>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
}
}
@@ -244,7 +244,7 @@ object FirErrors {
val INVALID_IF_AS_EXPRESSION by error0<FirSourceElement, KtIfExpression>(SourceElementPositioningStrategies.IF_EXPRESSION)
// Function contracts
val ERROR_IN_CONTRACT_DESCRIPTION by error1<FirSourceElement, KtElement, String>()
val ERROR_IN_CONTRACT_DESCRIPTION by error1<FirSourceElement, KtElement, String>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
// Extended checkers
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
@@ -254,7 +254,7 @@ object FirErrors {
val REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE by warning0<FirSourceElement, PsiElement>()
val CAN_BE_VAL by warning0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
val REDUNDANT_CALL_OF_CONVERSION_METHOD by warning0<FirSourceElement, PsiElement>()
val REDUNDANT_CALL_OF_CONVERSION_METHOD by warning0<FirSourceElement, PsiElement>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
val EMPTY_RANGE by warning0<FirSourceElement, PsiElement>()
val REDUNDANT_SETTER_PARAMETER_TYPE by warning0<FirSourceElement, PsiElement>()
@@ -262,6 +262,6 @@ object FirErrors {
val ASSIGNED_VALUE_IS_NEVER_READ by warning0<FirSourceElement, PsiElement>()
val VARIABLE_INITIALIZER_IS_REDUNDANT by warning0<FirSourceElement, PsiElement>()
val VARIABLE_NEVER_READ by warning0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
val USELESS_CALL_ON_NOT_NULL by warning0<FirSourceElement, PsiElement>()
val USELESS_CALL_ON_NOT_NULL by warning0<FirSourceElement, PsiElement>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
}
@@ -335,6 +335,24 @@ object LightTreePositioningStrategies {
}
}
val SELECTOR_BY_QUALIFIED: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
if (node.tokenType != KtNodeTypes.DOT_QUALIFIED_EXPRESSION && node.tokenType != KtNodeTypes.SAFE_ACCESS_EXPRESSION) {
return super.mark(node, startOffset, endOffset, tree)
}
val selector = tree.selector(node)
if (selector != null) {
return markElement(selector, startOffset, endOffset, tree, node)
}
return super.mark(node, startOffset, endOffset, tree)
}
}
val WHEN_EXPRESSION = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
@@ -448,6 +466,25 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.defaultValue(node: Lig
return null
}
private fun FlyweightCapableTreeStructure<LighterASTNode>.selector(node: LighterASTNode): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
val children = childrenRef.get() ?: return null
var dotFound = false
for (child in children) {
if (child == null) continue
if (child.tokenType == KtTokens.DOT) {
dotFound = true
continue
}
if (dotFound && (child.tokenType == KtNodeTypes.CALL_EXPRESSION || child.tokenType == KtNodeTypes.REFERENCE_EXPRESSION)) {
return child
}
}
return null
}
fun FlyweightCapableTreeStructure<LighterASTNode>.findChildByType(node: LighterASTNode, type: IElementType): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
@@ -103,6 +103,11 @@ object SourceElementPositioningStrategies {
PositioningStrategies.DOT_BY_SELECTOR
)
val SELECTOR_BY_QUALIFIED = SourceElementPositioningStrategy(
LightTreePositioningStrategies.SELECTOR_BY_QUALIFIED,
PositioningStrategies.SELECTOR_BY_QUALIFIED
)
val WHEN_EXPRESSION = SourceElementPositioningStrategy(
LightTreePositioningStrategies.WHEN_EXPRESSION,
PositioningStrategies.WHEN_EXPRESSION
@@ -725,4 +725,15 @@ object PositioningStrategies {
return super.mark(element)
}
}
val SELECTOR_BY_QUALIFIED: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
override fun mark(element: PsiElement): List<TextRange> {
if (element is KtQualifiedExpression) {
when (val selectorExpression = element.selectorExpression) {
is KtCallExpression, is KtReferenceExpression -> return mark(selectorExpression)
}
}
return super.mark(element)
}
}
}