[FIR][LightTree] Better expression identification
And some refactoring Regenerate IDE parts
This commit is contained in:
committed by
TeamCityServer
parent
2f7d6da22f
commit
5fc1514104
+25
-15
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
|
|||||||
import com.intellij.lang.LighterASTNode
|
import com.intellij.lang.LighterASTNode
|
||||||
import com.intellij.openapi.util.Ref
|
import com.intellij.openapi.util.Ref
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.impl.source.tree.ElementType
|
|
||||||
import com.intellij.psi.tree.IElementType
|
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
|
||||||
@@ -19,8 +18,8 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens.MODALITY_MODIFIERS
|
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.KtParameter.VAL_VAR_TOKEN_SET
|
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
|
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.elements.KtStringTemplateExpressionElementType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||||
|
|
||||||
object LightTreePositioningStrategies {
|
object LightTreePositioningStrategies {
|
||||||
@@ -644,20 +643,23 @@ internal fun FlyweightCapableTreeStructure<LighterASTNode>.nameIdentifier(node:
|
|||||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.operationReference(node: LighterASTNode): LighterASTNode? =
|
private fun FlyweightCapableTreeStructure<LighterASTNode>.operationReference(node: LighterASTNode): LighterASTNode? =
|
||||||
findChildByType(node, KtNodeTypes.OPERATION_REFERENCE)
|
findChildByType(node, KtNodeTypes.OPERATION_REFERENCE)
|
||||||
|
|
||||||
private val EXPRESSION_NODE_TYPES = setOf(
|
private val EXPRESSIONS_SET = listOf(
|
||||||
KtNodeTypes.REFERENCE_EXPRESSION,
|
KtNodeTypes.REFERENCE_EXPRESSION,
|
||||||
KtNodeTypes.CONSTRUCTOR_DELEGATION_REFERENCE,
|
|
||||||
KtNodeTypes.SUPER_EXPRESSION,
|
|
||||||
KtNodeTypes.ARRAY_ACCESS_EXPRESSION,
|
|
||||||
KtNodeTypes.CALL_EXPRESSION,
|
|
||||||
KtNodeTypes.LABELED_EXPRESSION,
|
|
||||||
KtNodeTypes.DOT_QUALIFIED_EXPRESSION,
|
KtNodeTypes.DOT_QUALIFIED_EXPRESSION,
|
||||||
KtNodeTypes.FUN,
|
|
||||||
KtNodeTypes.IF,
|
|
||||||
KtNodeTypes.STRING_TEMPLATE,
|
|
||||||
KtNodeTypes.LAMBDA_EXPRESSION,
|
KtNodeTypes.LAMBDA_EXPRESSION,
|
||||||
|
KtNodeTypes.FUN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun LighterASTNode.isExpression(): Boolean {
|
||||||
|
return when (this.tokenType) {
|
||||||
|
is KtNodeType,
|
||||||
|
is KtConstantExpressionElementType,
|
||||||
|
is KtStringTemplateExpressionElementType,
|
||||||
|
in EXPRESSIONS_SET -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for diagnostics
|
* @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for diagnostics
|
||||||
* on super and unresolved references. For example, with the following, only the part inside the parentheses should be highlighted.
|
* on super and unresolved references. For example, with the following, only the part inside the parentheses should be highlighted.
|
||||||
@@ -678,9 +680,7 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.referenceExpression(
|
|||||||
val childrenRef = Ref<Array<LighterASTNode?>>()
|
val childrenRef = Ref<Array<LighterASTNode?>>()
|
||||||
getChildren(node, childrenRef)
|
getChildren(node, childrenRef)
|
||||||
var result = childrenRef.get()?.firstOrNull {
|
var result = childrenRef.get()?.firstOrNull {
|
||||||
it?.tokenType in EXPRESSION_NODE_TYPES ||
|
it?.isExpression() == true || it?.tokenType == KtNodeTypes.PARENTHESIZED
|
||||||
it?.tokenType is KtConstantExpressionElementType ||
|
|
||||||
it?.tokenType == KtNodeTypes.PARENTHESIZED
|
|
||||||
}
|
}
|
||||||
while (locateReferencedName && result != null && result.tokenType == KtNodeTypes.PARENTHESIZED) {
|
while (locateReferencedName && result != null && result.tokenType == KtNodeTypes.PARENTHESIZED) {
|
||||||
result = referenceExpression(result, locateReferencedName = true)
|
result = referenceExpression(result, locateReferencedName = true)
|
||||||
@@ -689,7 +689,7 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.referenceExpression(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.findReferenceExpressionDeep(node: LighterASTNode): LighterASTNode? =
|
private fun FlyweightCapableTreeStructure<LighterASTNode>.findReferenceExpressionDeep(node: LighterASTNode): LighterASTNode? =
|
||||||
findDescendantByTypes(node, EXPRESSION_NODE_TYPES)
|
findFirstDescendant(node) { it.isExpression() }
|
||||||
|
|
||||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.rightParenthesis(node: LighterASTNode): LighterASTNode? =
|
private fun FlyweightCapableTreeStructure<LighterASTNode>.rightParenthesis(node: LighterASTNode): LighterASTNode? =
|
||||||
findChildByType(node, KtTokens.RPAR)
|
findChildByType(node, KtTokens.RPAR)
|
||||||
@@ -802,6 +802,16 @@ fun FlyweightCapableTreeStructure<LighterASTNode>.findDescendantByTypes(node: Li
|
|||||||
?.firstNotNullResult { child -> child?.let { findDescendantByTypes(it, types) } }
|
?.firstNotNullResult { child -> child?.let { findDescendantByTypes(it, types) } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FlyweightCapableTreeStructure<LighterASTNode>.findFirstDescendant(
|
||||||
|
node: LighterASTNode,
|
||||||
|
predicate: (LighterASTNode) -> Boolean
|
||||||
|
): LighterASTNode? {
|
||||||
|
val childrenRef = Ref<Array<LighterASTNode?>>()
|
||||||
|
getChildren(node, childrenRef)
|
||||||
|
return childrenRef.get()?.firstOrNull { it != null && predicate(it) }
|
||||||
|
?: childrenRef.get()?.firstNotNullResult { child -> child?.let { findFirstDescendant(it, predicate) } }
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ open enum class Z : Enum<Z> {
|
|||||||
fun test() {
|
fun test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class A {
|
local inner class A {
|
||||||
constructor() /* primary */ {
|
constructor() /* primary */ {
|
||||||
super/*Any*/()
|
super/*Any*/()
|
||||||
/* <init>() */
|
/* <init>() */
|
||||||
@@ -36,3 +36,4 @@ open enum class Z : Enum<Z> {
|
|||||||
fun valueOf(value: String): Z /* Synthetic body for ENUM_VALUEOF */
|
fun valueOf(value: String): Z /* Synthetic body for ENUM_VALUEOF */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -113,8 +113,8 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
|||||||
FirErrors.SYNTAX.on(FirRealPsiSourceElement(it)).toMetaInfo(testFile, lightTreeEnabled, lightTreeComparingModeEnabled)
|
FirErrors.SYNTAX.on(FirRealPsiSourceElement(it)).toMetaInfo(testFile, lightTreeEnabled, lightTreeComparingModeEnabled)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
collectLightTreeSyntaxErrors(firFile).map { node ->
|
collectLightTreeSyntaxErrors(firFile).map { sourceElement ->
|
||||||
FirErrors.SYNTAX.on(node).toMetaInfo(testFile, lightTreeEnabled, lightTreeComparingModeEnabled)
|
FirErrors.SYNTAX.on(sourceElement).toMetaInfo(testFile, lightTreeEnabled, lightTreeComparingModeEnabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -48,12 +48,12 @@ private class LightTreeErrorsCollector(private val tree: Tree) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class OffsetTree(val tree: Tree, val offset: Int)
|
private data class TreeWithOffset(val tree: Tree, val offset: Int)
|
||||||
|
|
||||||
private data class VisitorState(
|
private data class VisitorState(
|
||||||
val lastTree: Tree? = null,
|
val lastTree: Tree? = null,
|
||||||
val visitedTrees: MutableSet<Tree> = mutableSetOf(),
|
val visitedTrees: MutableSet<Tree> = mutableSetOf(),
|
||||||
val result: MutableList<OffsetTree> = mutableListOf()
|
val result: MutableList<TreeWithOffset> = mutableListOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
private object FirTreesExtractVisitor : FirVisitor<Unit, VisitorState>() {
|
private object FirTreesExtractVisitor : FirVisitor<Unit, VisitorState>() {
|
||||||
@@ -62,7 +62,7 @@ private object FirTreesExtractVisitor : FirVisitor<Unit, VisitorState>() {
|
|||||||
val currentTree = source.treeStructure
|
val currentTree = source.treeStructure
|
||||||
val (lastTree, visitedTrees, result) = data
|
val (lastTree, visitedTrees, result) = data
|
||||||
val newData = if (lastTree !== currentTree && visitedTrees.add(currentTree)) {
|
val newData = if (lastTree !== currentTree && visitedTrees.add(currentTree)) {
|
||||||
val newTreeWithOffset = OffsetTree(currentTree, element.source?.startOffset ?: 0)
|
val newTreeWithOffset = TreeWithOffset(currentTree, element.source?.startOffset ?: 0)
|
||||||
result.add(newTreeWithOffset)
|
result.add(newTreeWithOffset)
|
||||||
data.copy(lastTree = lastTree)
|
data.copy(lastTree = lastTree)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -759,7 +759,7 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = CyclicGenericUpperBound::class
|
override val diagnosticClass get() = CyclicGenericUpperBound::class
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class DeprecatedTypeParameterSyntax : KtFirDiagnostic<KtTypeParameterList>() {
|
abstract class DeprecatedTypeParameterSyntax : KtFirDiagnostic<KtDeclaration>() {
|
||||||
override val diagnosticClass get() = DeprecatedTypeParameterSyntax::class
|
override val diagnosticClass get() = DeprecatedTypeParameterSyntax::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1228,7 +1228,7 @@ internal class CyclicGenericUpperBoundImpl(
|
|||||||
internal class DeprecatedTypeParameterSyntaxImpl(
|
internal class DeprecatedTypeParameterSyntaxImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtFirDiagnostic.DeprecatedTypeParameterSyntax(), KtAbstractFirDiagnostic<KtTypeParameterList> {
|
) : KtFirDiagnostic.DeprecatedTypeParameterSyntax(), KtAbstractFirDiagnostic<KtDeclaration> {
|
||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user