Move specific diagnostics infrastructure to frontend.common-psi

This commit is contained in:
Ilya Chernikov
2021-09-20 19:43:09 +02:00
parent e9f59e8d1d
commit d3f3aa4b29
21 changed files with 49 additions and 42 deletions
@@ -117,7 +117,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
val expressionToCreate get() = "SourceElementPositioningStrategies.${strategy ?: name}"
companion object {
const val importToAdd = "org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies"
const val importToAdd = "org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies"
}
}
@@ -12,8 +12,8 @@ import org.jetbrains.kotlin.config.LanguageFeature.ProhibitJvmOverloadsOnConstru
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitSpreadOnSignaturePolymorphicCall
import org.jetbrains.kotlin.config.LanguageFeature.RepeatableAnnotationContainerConstraints
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.ClassId
@@ -23,9 +23,9 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.analysis.diagnostics.SourceElementPositioningStrategies
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -13,6 +13,9 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.modalityModifier
import org.jetbrains.kotlin.diagnostics.overrideModifier
import org.jetbrains.kotlin.diagnostics.visibilityModifier
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
@@ -11,7 +11,7 @@ import com.intellij.psi.tree.TokenSet
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.valOrVarKeyword
import org.jetbrains.kotlin.diagnostics.valOrVarKeyword
import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
@@ -14,8 +14,8 @@ import org.jetbrains.kotlin.KtPsiSourceElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.getAncestors
import org.jetbrains.kotlin.fir.analysis.diagnostics.nameIdentifier
import org.jetbrains.kotlin.diagnostics.getAncestors
import org.jetbrains.kotlin.diagnostics.nameIdentifier
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.hasValOrVar
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -11,6 +11,8 @@ import org.jetbrains.kotlin.descriptors.ClassKind.ANNOTATION_CLASS
import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_CLASS
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.hasValOrVar
import org.jetbrains.kotlin.diagnostics.hasVar
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.hasPrimaryConstructor
import org.jetbrains.kotlin.diagnostics.hasPrimaryConstructor
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.implicitModality
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirDeclarationSyntaxChecker
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
import org.jetbrains.kotlin.diagnostics.modalityModifier
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
@@ -11,6 +11,8 @@ import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.overrideModifier
import org.jetbrains.kotlin.diagnostics.visibilityModifier
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.fir.analysis.checkers.findClosestClassOrObject
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.diagnostics.typeParametersList
import org.jetbrains.kotlin.diagnostics.typeParametersList
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.psi.KtFunction
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.KtLightSourceElement
import org.jetbrains.kotlin.KtPsiSourceElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.nameIdentifier
import org.jetbrains.kotlin.diagnostics.typeParametersList
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.diagnostics.typeParametersList
import org.jetbrains.kotlin.diagnostics.typeParametersList
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtProperty
@@ -1,105 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.lang.LighterASTNode
import com.intellij.openapi.util.Ref
import com.intellij.openapi.util.TextRange
import com.intellij.psi.TokenType
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.WHITE_SPACE
open class LightTreePositioningStrategy {
open fun markKtDiagnostic(element: KtSourceElement, diagnostic: KtDiagnostic): List<TextRange> {
return mark(element.lighterASTNode, element.startOffset, element.endOffset, element.treeStructure)
}
open fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
return markElement(node, startOffset, endOffset, tree)
}
open fun isValid(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean {
return !hasSyntaxErrors(node, tree)
}
}
fun markElement(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>,
originalNode: LighterASTNode = node,
): List<TextRange> = markRange(node, node, startOffset, endOffset, tree, originalNode)
fun markRange(
from: LighterASTNode,
to: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>,
originalNode: LighterASTNode
): List<TextRange> {
return listOf(markSingleElement(from, to, startOffset, endOffset, tree, originalNode))
}
fun markSingleElement(
from: LighterASTNode,
to: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>,
originalNode: LighterASTNode
): TextRange {
val betterFrom = from.nonFillerFirstChildOrSelf(tree)
val betterTo = to.nonFillerLastChildOrSelf(tree)
val startDelta = tree.getStartOffset(betterFrom) - tree.getStartOffset(originalNode)
val endDelta = tree.getEndOffset(betterTo) - tree.getEndOffset(originalNode)
return TextRange(startDelta + startOffset, endDelta + endOffset)
}
private val DOC_AND_COMMENT_TOKENS = setOf(
WHITE_SPACE, KtTokens.IDENTIFIER,
KtTokens.EOL_COMMENT, KtTokens.BLOCK_COMMENT, KtTokens.SHEBANG_COMMENT, KtTokens.DOC_COMMENT
)
private val FILLER_TOKENS = setOf(
KtTokens.WHITE_SPACE,
KtTokens.EOL_COMMENT,
KtTokens.BLOCK_COMMENT,
KtTokens.SHEBANG_COMMENT,
KtTokens.DOC_COMMENT,
)
private fun LighterASTNode.nonFillerFirstChildOrSelf(tree: FlyweightCapableTreeStructure<LighterASTNode>): LighterASTNode =
getChildren(tree).firstOrNull { !it.isFiller() } ?: this
internal fun LighterASTNode.nonFillerLastChildOrSelf(tree: FlyweightCapableTreeStructure<LighterASTNode>): LighterASTNode =
getChildren(tree).lastOrNull { !it.isFiller() } ?: this
internal fun LighterASTNode.isFiller() = tokenType in FILLER_TOKENS
private fun hasSyntaxErrors(node: LighterASTNode, tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean {
if (node.tokenType == TokenType.ERROR_ELEMENT) return true
val childrenRef = Ref<Array<LighterASTNode?>?>()
tree.getChildren(node, childrenRef)
val children = childrenRef.get() ?: return false
return children.filterNotNull().lastOrNull {
val tokenType = it.tokenType
tokenType !is KtSingleValueToken && tokenType !in DOC_AND_COMMENT_TOKENS
}?.let { hasSyntaxErrors(it, tree) } == true
}
@@ -1,47 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtPsiSourceElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.cfg.UnreachableCode
import org.jetbrains.kotlin.diagnostics.DiagnosticMarker
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.diagnostics.KtDiagnosticWithParameters2
import org.jetbrains.kotlin.diagnostics.PositioningStrategy
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtNamedDeclaration
object PsiPositioningStrategies {
val UNREACHABLE_CODE = object : PositioningStrategy<PsiElement>() {
override fun markDiagnostic(diagnostic: DiagnosticMarker): List<TextRange> {
//todo it is better to implement arguments extraction in KtDiagnosticFactory, but kotlin struggle with checking types in it atm
@Suppress("UNCHECKED_CAST")
val typed = diagnostic as KtDiagnosticWithParameters2<Set<KtSourceElement>, Set<KtSourceElement>>
val source = diagnostic.element as KtPsiSourceElement
return UnreachableCode.getUnreachableTextRanges(
source.psi as KtElement,
typed.a.mapNotNull { it.psi as? KtElement }.toSet(),
typed.b.mapNotNull { it.psi as? KtElement }.toSet()
)
}
}
val ACTUAL_DECLARATION_NAME = object : PositioningStrategy<PsiElement>() {
override fun markDiagnostic(diagnostic: DiagnosticMarker): List<TextRange> {
require(diagnostic is KtDiagnostic)
val element = diagnostic.element.psi ?: return emptyList()
(element as? KtNamedDeclaration)?.nameIdentifier?.let { nameIdentifier ->
return mark(nameIdentifier)
}
return mark(element)
}
}
}
@@ -1,350 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.diagnostics
import org.jetbrains.kotlin.diagnostics.AbstractSourceElementPositioningStrategy
import org.jetbrains.kotlin.diagnostics.PositioningStrategies
object SourceElementPositioningStrategies {
val DEFAULT = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DEFAULT,
PositioningStrategies.DEFAULT
).also {
AbstractSourceElementPositioningStrategy.setDefault(it)
}
val VAL_OR_VAR_NODE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.VAL_OR_VAR_NODE,
PositioningStrategies.VAL_OR_VAR_NODE
)
val FUN_INTERFACE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.FUN_INTERFACE,
PositioningStrategies.FUN_INTERFACE
)
val COMPANION_OBJECT = SourceElementPositioningStrategy(
LightTreePositioningStrategies.COMPANION_OBJECT,
PositioningStrategies.COMPANION_OBJECT
)
val SECONDARY_CONSTRUCTOR_DELEGATION_CALL = SourceElementPositioningStrategy(
LightTreePositioningStrategies.SECONDARY_CONSTRUCTOR_DELEGATION_CALL,
PositioningStrategies.SECONDARY_CONSTRUCTOR_DELEGATION_CALL
)
val DECLARATION_RETURN_TYPE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DECLARATION_RETURN_TYPE,
PositioningStrategies.DECLARATION_RETURN_TYPE
)
val DECLARATION_NAME = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DECLARATION_NAME,
PositioningStrategies.DECLARATION_NAME
)
val DECLARATION_SIGNATURE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DECLARATION_SIGNATURE,
PositioningStrategies.DECLARATION_SIGNATURE
)
val DECLARATION_SIGNATURE_OR_DEFAULT = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT,
PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT
)
val VISIBILITY_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.VISIBILITY_MODIFIER,
PositioningStrategies.VISIBILITY_MODIFIER
)
val MODALITY_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.MODALITY_MODIFIER,
PositioningStrategies.MODALITY_MODIFIER
)
val ABSTRACT_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.ABSTRACT_MODIFIER,
PositioningStrategies.ABSTRACT_MODIFIER
)
val OPEN_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.OPEN_MODIFIER,
PositioningStrategies.OPEN_MODIFIER
)
val OVERRIDE_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.OVERRIDE_MODIFIER,
PositioningStrategies.OVERRIDE_MODIFIER
)
val PRIVATE_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.PRIVATE_MODIFIER,
PositioningStrategies.PRIVATE_MODIFIER
)
val LATEINIT_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.LATEINIT_MODIFIER,
PositioningStrategies.LATEINIT_MODIFIER
)
val VARIANCE_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.VARIANCE_MODIFIER,
PositioningStrategies.VARIANCE_MODIFIER
)
val CONST_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.CONST_MODIFIER,
PositioningStrategies.CONST_MODIFIER
)
val INLINE_OR_VALUE_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.INLINE_OR_VALUE_MODIFIER,
PositioningStrategies.INLINE_OR_VALUE_MODIFIER
)
val INNER_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.INNER_MODIFIER,
PositioningStrategies.INNER_MODIFIER
)
val FUN_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.FUN_MODIFIER,
PositioningStrategies.FUN_MODIFIER
)
val SUSPEND_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.SUSPEND_MODIFIER,
PositioningStrategies.SUSPEND_MODIFIER
)
val DATA_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DATA_MODIFIER,
PositioningStrategies.DATA_MODIFIER
)
val OPERATOR = SourceElementPositioningStrategy(
LightTreePositioningStrategies.OPERATOR,
PositioningStrategies.OPERATOR
)
val PARAMETER_DEFAULT_VALUE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.PARAMETER_DEFAULT_VALUE,
PositioningStrategies.PARAMETER_DEFAULT_VALUE
)
val PARAMETER_VARARG_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.PARAMETER_VARARG_MODIFIER,
PositioningStrategies.PARAMETER_VARARG_MODIFIER
)
val NAME_OF_NAMED_ARGUMENT = SourceElementPositioningStrategy(
LightTreePositioningStrategies.NAME_OF_NAMED_ARGUMENT,
PositioningStrategies.NAME_OF_NAMED_ARGUMENT
)
val VALUE_ARGUMENTS = SourceElementPositioningStrategy(
LightTreePositioningStrategies.VALUE_ARGUMENTS,
PositioningStrategies.VALUE_ARGUMENTS
)
val SUPERTYPES_LIST = SourceElementPositioningStrategy(
LightTreePositioningStrategies.SUPERTYPES_LIST,
PositioningStrategies.SUPERTYPES_LIST
)
val DOT_BY_QUALIFIED = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DOT_BY_QUALIFIED,
PositioningStrategies.DOT_BY_QUALIFIED
)
val SELECTOR_BY_QUALIFIED = SourceElementPositioningStrategy(
LightTreePositioningStrategies.SELECTOR_BY_QUALIFIED,
PositioningStrategies.SELECTOR_BY_QUALIFIED
)
val REFERENCE_BY_QUALIFIED = SourceElementPositioningStrategy(
LightTreePositioningStrategies.REFERENCE_BY_QUALIFIED,
PositioningStrategies.REFERENCE_BY_QUALIFIED
)
val REFERENCED_NAME_BY_QUALIFIED = SourceElementPositioningStrategy(
LightTreePositioningStrategies.REFERENCED_NAME_BY_QUALIFIED,
PositioningStrategies.REFERENCED_NAME_BY_QUALIFIED
)
val WHEN_EXPRESSION = SourceElementPositioningStrategy(
LightTreePositioningStrategies.WHEN_EXPRESSION,
PositioningStrategies.WHEN_EXPRESSION
)
val IF_EXPRESSION = SourceElementPositioningStrategy(
LightTreePositioningStrategies.IF_EXPRESSION,
PositioningStrategies.IF_EXPRESSION
)
val ELSE_ENTRY = SourceElementPositioningStrategy(
LightTreePositioningStrategies.ELSE_ENTRY,
PositioningStrategies.ELSE_ENTRY
)
val ARRAY_ACCESS = SourceElementPositioningStrategy(
LightTreePositioningStrategies.ARRAY_ACCESS,
PositioningStrategies.ARRAY_ACCESS
)
val SAFE_ACCESS = SourceElementPositioningStrategy(
LightTreePositioningStrategies.SAFE_ACCESS,
PositioningStrategies.SAFE_ACCESS
)
val AS_TYPE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.AS_TYPE,
PositioningStrategies.AS_TYPE
)
val USELESS_ELVIS = SourceElementPositioningStrategy(
LightTreePositioningStrategies.USELESS_ELVIS,
PositioningStrategies.USELESS_ELVIS
)
val RETURN_WITH_LABEL = SourceElementPositioningStrategy(
LightTreePositioningStrategies.RETURN_WITH_LABEL,
PositioningStrategies.RETURN_WITH_LABEL
)
val PROPERTY_INITIALIZER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.LAST_CHILD,
PositioningStrategies.PROPERTY_INITIALIZER
)
val WHOLE_ELEMENT = SourceElementPositioningStrategy(
LightTreePositioningStrategies.WHOLE_ELEMENT,
PositioningStrategies.WHOLE_ELEMENT
)
val LONG_LITERAL_SUFFIX = SourceElementPositioningStrategy(
LightTreePositioningStrategies.LONG_LITERAL_SUFFIX,
PositioningStrategies.LONG_LITERAL_SUFFIX
)
val REIFIED_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.REIFIED_MODIFIER,
PositioningStrategies.REIFIED_MODIFIER
)
val TYPE_PARAMETERS_LIST = SourceElementPositioningStrategy(
LightTreePositioningStrategies.TYPE_PARAMETERS_LIST,
PositioningStrategies.TYPE_PARAMETERS_LIST
)
val NAME_IDENTIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.NAME_IDENTIFIER,
PositioningStrategies.NAME_IDENTIFIER
)
val QUESTION_MARK_BY_TYPE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.QUESTION_MARK_BY_TYPE,
PositioningStrategies.QUESTION_MARK_BY_TYPE
)
val ANNOTATION_USE_SITE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.ANNOTATION_USE_SITE,
PositioningStrategies.ANNOTATION_USE_SITE
)
val ASSIGNMENT_LHS = SourceElementPositioningStrategy(
LightTreePositioningStrategies.ASSIGNMENT_LHS,
PositioningStrategies.ASSIGNMENT_LHS
)
val IMPORT_LAST_NAME = SourceElementPositioningStrategy(
LightTreePositioningStrategies.IMPORT_LAST_NAME,
PositioningStrategies.IMPORT_LAST_NAME
)
val SPREAD_OPERATOR = SourceElementPositioningStrategy(
LightTreePositioningStrategies.SPREAD_OPERATOR,
PositioningStrategies.SPREAD_OPERATOR
)
val DECLARATION_WITH_BODY = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DECLARATION_WITH_BODY,
PositioningStrategies.DECLARATION_WITH_BODY
)
val COMMAS = SourceElementPositioningStrategy(
LightTreePositioningStrategies.COMMAS,
PositioningStrategies.COMMAS
)
val UNREACHABLE_CODE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.UNREACHABLE_CODE,
PsiPositioningStrategies.UNREACHABLE_CODE
)
val ACTUAL_DECLARATION_NAME = SourceElementPositioningStrategy(
LightTreePositioningStrategies.ACTUAL_DECLARATION_NAME,
PsiPositioningStrategies.ACTUAL_DECLARATION_NAME
)
val LABEL = SourceElementPositioningStrategy(
LightTreePositioningStrategies.LABEL,
PositioningStrategies.LABEL
)
// TODO
val INCOMPATIBLE_DECLARATION = DEFAULT
val NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT = SourceElementPositioningStrategy(
LightTreePositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT,
PositioningStrategies.NOT_SUPPORTED_IN_INLINE_MOST_RELEVANT
)
val INLINE_PARAMETER_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.INLINE_PARAMETER_MODIFIER,
PositioningStrategies.INLINE_PARAMETER_MODIFIER
)
val OPERATOR_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.OPERATOR_MODIFIER,
PositioningStrategies.OPERATOR_MODIFIER
)
val NON_FINAL_MODIFIER_OR_NAME = SourceElementPositioningStrategy(
LightTreePositioningStrategies.NON_FINAL_MODIFIER_OR_NAME,
PositioningStrategies.NON_FINAL_MODIFIER_OR_NAME
)
val ENUM_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.ENUM_MODIFIER,
PositioningStrategies.ENUM_MODIFIER
)
val FIELD_KEYWORD = SourceElementPositioningStrategy(
LightTreePositioningStrategies.FIELD_KEYWORD,
PositioningStrategies.FIELD_KEYWORD
)
val TAILREC_MODIFIER = SourceElementPositioningStrategy(
LightTreePositioningStrategies.TAILREC_MODIFIER,
PositioningStrategies.TAILREC_MODIFIER
)
val PROPERTY_DELEGATE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.PROPERTY_DELEGATE,
PositioningStrategies.PROPERTY_DELEGATE
)
val IMPORT_ALIAS = SourceElementPositioningStrategy(
LightTreePositioningStrategies.IMPORT_ALIAS,
PositioningStrategies.IMPORT_ALIAS
)
val DECLARATION_START_TO_NAME = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DECLARATION_START_TO_NAME,
PositioningStrategies.DECLARATION_START_TO_NAME
)
}
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtLightSourceElement
import org.jetbrains.kotlin.KtPsiSourceElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.diagnostics.AbstractSourceElementPositioningStrategy
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.diagnostics.PositioningStrategy
class SourceElementPositioningStrategy(
private val lightTreeStrategy: LightTreePositioningStrategy,
private val psiStrategy: PositioningStrategy<*>
) : AbstractSourceElementPositioningStrategy() {
override fun markDiagnostic(diagnostic: KtDiagnostic): List<TextRange> {
return when (val element = diagnostic.element) {
is KtPsiSourceElement -> psiStrategy.markDiagnostic(diagnostic)
is KtLightSourceElement -> lightTreeStrategy.markKtDiagnostic(element, diagnostic)
}
}
override fun isValid(element: KtSourceElement): Boolean {
return when (element) {
is KtPsiSourceElement -> psiStrategy.hackyIsValid(element.psi)
is KtLightSourceElement -> lightTreeStrategy.isValid(element.lighterASTNode, element.treeStructure)
}
}
private fun PositioningStrategy<*>.hackyIsValid(psi: PsiElement): Boolean {
@Suppress("UNCHECKED_CAST")
return (this as PositioningStrategy<PsiElement>).isValid(psi)
}
}
@@ -1,86 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.lang.LighterASTNode
import com.intellij.openapi.util.TextRange
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
import org.jetbrains.kotlin.lexer.KtTokens
typealias Node = LighterASTNode
class UnreachableCodeLightTreeHelper(val tree: FlyweightCapableTreeStructure<Node>) {
fun Node.hasChildrenInSet(set: Set<Node>): Boolean {
var result = false
tree.traverseDescendants(this) {
if (!result && it != this && it in set) {
result = true
}
!result
}
return result
}
fun Node.getLeavesOrReachableChildren(reachable: Set<Node>, unreachable: Set<Node>): List<Node> {
val result = mutableListOf<Node>()
tree.traverseDescendants(this) { element ->
val isReachable = element in reachable && !element.hasChildrenInSet(unreachable)
if (isReachable || element.getChildren(tree).isEmpty()) {
result.add(element)
false
} else {
true
}
}
return result
}
fun List<Node>.removeReachableElementsWithMeaninglessSiblings(reachableElements: Set<Node>): List<Node> {
val childrenToRemove = mutableSetOf<Node>()
fun collectSiblingsIfMeaningless(elementIndex: Int, direction: Int) {
val index = elementIndex + direction
if (index !in 0 until size) return
val element = this[index]
if (element.isFiller() || element.tokenType == KtTokens.COMMA) {
childrenToRemove.add(element)
collectSiblingsIfMeaningless(index, direction)
}
}
for ((index, element) in this.withIndex()) {
if (reachableElements.contains(element)) {
childrenToRemove.add(element)
collectSiblingsIfMeaningless(index, -1)
collectSiblingsIfMeaningless(index, 1)
}
}
return filter { it !in childrenToRemove }
}
fun List<TextRange>.mergeAdjacentTextRanges(): List<TextRange> {
val result = ArrayList<TextRange>()
val lastRange = fold(null as TextRange?) { currentTextRange, elementRange ->
when {
currentTextRange == null -> {
elementRange
}
currentTextRange.endOffset == elementRange.startOffset -> {
currentTextRange.union(elementRange)
}
else -> {
result.add(currentTextRange)
elementRange
}
}
}
if (lastRange != null) {
result.add(lastRange)
}
return result
}
}