From 1cb2aeaeff10a83769ce00d71c7045bbc1d38e33 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 16 Nov 2020 17:03:49 +0300 Subject: [PATCH] FirSourceElement: introduce common 'treeStructure' property --- .../kotlin/fir/analysis/FirSourceChildren.kt | 4 +- .../fir/analysis/checkers/FirModifierList.kt | 4 +- .../FirAnnotationArgumentChecker.kt | 4 +- .../FirAnnotationClassDeclarationChecker.kt | 2 +- .../FirConstructorInInterfaceChecker.kt | 2 +- .../FirDelegationInInterfaceChecker.kt | 2 +- .../FirExposedVisibilityDeclarationChecker.kt | 4 +- ...rSupertypeInitializedInInterfaceChecker.kt | 2 +- ...ypeInitializedWithoutPrimaryConstructor.kt | 2 +- ...ypeArgumentsNotAllowedExpressionChecker.kt | 2 +- ...BeReplacedWithOperatorAssignmentChecker.kt | 2 +- .../checkers/extended/CanBeValChecker.kt | 2 +- ...ntSingleExpressionStringTemplateChecker.kt | 4 +- .../fir/lightTree/fir/ValueParameter.kt | 2 +- .../jetbrains/kotlin/fir/FirSourceElement.kt | 38 ++++++++++++++++++- 15 files changed, 55 insertions(+), 21 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirSourceChildren.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirSourceChildren.kt index 40d8c8f5d2fdc..b698d7cfff1aa 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirSourceChildren.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirSourceChildren.kt @@ -35,7 +35,7 @@ private fun FirPsiSourceElement<*>.getChild(types: Set, index: Int } private fun FirLightSourceElement.getChild(types: Set, index: Int, depth: Int): FirSourceElement? { - val visitor = LighterTreeElementFinderByType(tree, types, index, depth) + val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth) - return visitor.find(lighterASTNode)?.let { it.toFirLightSourceElement(it.startOffset, it.endOffset, tree) } + return visitor.find(lighterASTNode)?.let { it.toFirLightSourceElement(it.startOffset, it.endOffset, treeStructure) } } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirModifierList.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirModifierList.kt index dba6f998b872f..ec7b5f0237403 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirModifierList.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirModifierList.kt @@ -28,9 +28,9 @@ fun FirSourceElement?.getModifierList(): FirModifierList? { is FirPsiSourceElement<*> -> (psi as? KtModifierListOwner)?.modifierList?.let { FirPsiModifierList(it) } is FirLightSourceElement -> { val kidsRef = Ref>() - tree.getChildren(lighterASTNode, kidsRef) + treeStructure.getChildren(lighterASTNode, kidsRef) val modifierListNode = kidsRef.get().find { it?.tokenType == KtNodeTypes.MODIFIER_LIST } ?: return null - FirLightModifierList(modifierListNode, tree) + FirLightModifierList(modifierListNode, treeStructure) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationArgumentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationArgumentChecker.kt index 0d2a46e10b937..6ec8f2a054c76 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationArgumentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationArgumentChecker.kt @@ -241,9 +241,9 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() { is FirPsiSourceElement<*> -> source.psi.parent.toFirPsiSourceElement() is FirLightSourceElement -> { - val elementOfParent = source.tree.getParent(source.lighterASTNode) ?: source.lighterASTNode + val elementOfParent = source.treeStructure.getParent(source.lighterASTNode) ?: source.lighterASTNode - elementOfParent.toFirLightSourceElement(elementOfParent.startOffset, elementOfParent.endOffset, source.tree) + elementOfParent.toFirLightSourceElement(elementOfParent.startOffset, elementOfParent.endOffset, source.treeStructure) } else -> source diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt index 83c75be60852f..124933ff5edfd 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirAnnotationClassDeclarationChecker.kt @@ -53,7 +53,7 @@ object FirAnnotationClassDeclarationChecker : FirBasicDeclarationChecker() { } is FirLightSourceElement -> { val kidsRef = Ref>() - parameterSourceElement.tree.getChildren(parameterSourceElement.lighterASTNode, kidsRef) + parameterSourceElement.treeStructure.getChildren(parameterSourceElement.lighterASTNode, kidsRef) if (kidsRef.get().any { it?.tokenType == VAR_KEYWORD }) reporter.report(parameterSourceElement, FirErrors.VAR_ANNOTATION_PARAMETER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstructorInInterfaceChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstructorInInterfaceChecker.kt index 7ada834666c03..36caea305fe17 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstructorInInterfaceChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConstructorInInterfaceChecker.kt @@ -40,7 +40,7 @@ object FirConstructorInInterfaceChecker : FirBasicDeclarationChecker() { if (localPsi != null && localPsi !is PsiErrorElement) { return localPsi.hasPrimaryConstructor() } else if (this is FirLightSourceElement) { - return localLightNode.hasPrimaryConstructor(tree) + return localLightNode.hasPrimaryConstructor(treeStructure) } return false diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegationInInterfaceChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegationInInterfaceChecker.kt index c98213ba7fdc2..476966fbe537f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegationInInterfaceChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegationInInterfaceChecker.kt @@ -40,7 +40,7 @@ object FirDelegationInInterfaceChecker : FirMemberDeclarationChecker() { if (localPsi != null && localPsi !is PsiErrorElement) { return localPsi.findSuperTypeDelegation() } else if (this is FirLightSourceElement) { - return localLightNode.findSuperTypeDelegation(tree) + return localLightNode.findSuperTypeDelegation(treeStructure) } return -1 diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExposedVisibilityDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExposedVisibilityDeclarationChecker.kt index 46b8c798cbb7d..ea7ad8510fa98 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExposedVisibilityDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExposedVisibilityDeclarationChecker.kt @@ -234,9 +234,9 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() { is FirPsiSourceElement<*> -> (this.psi as? PsiNameIdentifierOwner)?.nameIdentifier?.toFirPsiSourceElement() is FirLightSourceElement -> { val kidsRef = Ref>() - this.tree.getChildren(lighterASTNode, kidsRef) + this.treeStructure.getChildren(lighterASTNode, kidsRef) val identifier = kidsRef.get().find { it?.tokenType == KtTokens.IDENTIFIER } - identifier?.toFirLightSourceElement(this.tree.getStartOffset(identifier), this.tree.getEndOffset(identifier), this.tree) + identifier?.toFirLightSourceElement(this.treeStructure.getStartOffset(identifier), this.treeStructure.getEndOffset(identifier), this.treeStructure) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypeInitializedInInterfaceChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypeInitializedInInterfaceChecker.kt index b69a4575cdcb8..6a1a4deb5d63c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypeInitializedInInterfaceChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypeInitializedInInterfaceChecker.kt @@ -40,7 +40,7 @@ object FirSupertypeInitializedInInterfaceChecker : FirMemberDeclarationChecker() if (localPsi != null && localPsi !is PsiErrorElement) { return localPsi.findSuperTypeCall() } else if (this is FirLightSourceElement) { - return localLightNode.findSuperTypeCall(tree) + return localLightNode.findSuperTypeCall(treeStructure) } return -1 diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypeInitializedWithoutPrimaryConstructor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypeInitializedWithoutPrimaryConstructor.kt index 898935b10199e..b3f44874443e3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypeInitializedWithoutPrimaryConstructor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSupertypeInitializedWithoutPrimaryConstructor.kt @@ -44,7 +44,7 @@ object FirSupertypeInitializedWithoutPrimaryConstructor : FirMemberDeclarationCh if (localPsi != null && localPsi !is PsiErrorElement) { return localPsi.anySupertypeHasConstructorParentheses() } else if (this is FirLightSourceElement) { - return localLightNode.anySupertypeHasConstructorParentheses(tree) + return localLightNode.anySupertypeHasConstructorParentheses(treeStructure) } return false diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeArgumentsNotAllowedExpressionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeArgumentsNotAllowedExpressionChecker.kt index b902ba825ef79..0e3f306a8ba10 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeArgumentsNotAllowedExpressionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeArgumentsNotAllowedExpressionChecker.kt @@ -42,7 +42,7 @@ object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessChecker() if (localPsi != null && localPsi !is PsiErrorElement) { return localPsi.hasAnyArguments() } else if (this is FirLightSourceElement) { - return localLight.hasAnyArguments(this.tree) + return localLight.hasAnyArguments(this.treeStructure) } return false diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt index 873695acb445a..0486053f2f3ee 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeReplacedWithOperatorAssignmentChecker.kt @@ -71,7 +71,7 @@ object CanBeReplacedWithOperatorAssignmentChecker : FirExpressionChecker>() tree.getChildren(expression, childrenNullable) val children = childrenNullable.get().filterNotNull() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeValChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeValChecker.kt index c746feb47e7f4..1ed0369812bd0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeValChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/CanBeValChecker.kt @@ -102,7 +102,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() { is FirPsiSourceElement<*> -> fir.psi?.children?.size?.minus(1) // -1 cuz we don't need expression node after equals operator is FirLightSourceElement -> { val source = fir.source as FirLightSourceElement - val tree = (fir.source as FirLightSourceElement).tree + val tree = (fir.source as FirLightSourceElement).treeStructure val children = Ref>() tree.getChildren(source.lighterASTNode, children) children.get().filterNotNull().filter { it.tokenType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY }.size diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSingleExpressionStringTemplateChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSingleExpressionStringTemplateChecker.kt index 301e9f554fe4f..be4b8c50a4323 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSingleExpressionStringTemplateChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantSingleExpressionStringTemplateChecker.kt @@ -54,10 +54,10 @@ object RedundantSingleExpressionStringTemplateChecker : FirBasicExpressionChecke } private fun LighterASTNode.stringParentChildrenCount(source: FirLightSourceElement): Int? { - val parent = source.tree.getParent(this) + val parent = source.treeStructure.getParent(this) return if (parent?.tokenType == KtNodeTypes.STRING_TEMPLATE) { val childrenOfParent = Ref>() - source.tree.getChildren(parent!!, childrenOfParent) + source.treeStructure.getChildren(parent!!, childrenOfParent) childrenOfParent.get().filter { it is PsiBuilder.Marker }.size } else { parent?.stringParentChildrenCount(source) diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt index a579dbd9a7c7f..9573f985fba36 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/fir/ValueParameter.kt @@ -46,7 +46,7 @@ class ValueParameter( val parameterSource = firValueParameter.source as? FirLightSourceElement val parameterNode = parameterSource?.lighterASTNode source = parameterNode?.toFirLightSourceElement( - parameterSource.startOffset, parameterSource.endOffset, parameterSource.tree, + parameterSource.startOffset, parameterSource.endOffset, parameterSource.treeStructure, FirFakeSourceElementKind.PropertyFromParameter ) this.session = session diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt index 4ab52409b9795..b4ac9b28b32b2 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt @@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir import com.intellij.lang.LighterASTNode import com.intellij.lang.TreeBackedLighterAST +import com.intellij.openapi.util.Ref import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import com.intellij.psi.tree.IElementType import com.intellij.util.diff.FlyweightCapableTreeStructure @@ -154,6 +156,7 @@ sealed class FirSourceElement { abstract val endOffset: Int abstract val kind: FirSourceElementKind abstract val lighterASTNode: LighterASTNode + abstract val treeStructure: FlyweightCapableTreeStructure } // NB: in certain situations, psi.node could be null @@ -169,6 +172,37 @@ sealed class FirPsiSourceElement(val psi: P) : FirSourceElem get() = psi.textRange.endOffset override val lighterASTNode by lazy { TreeBackedLighterAST.wrap(psi.node) } + + override val treeStructure: FlyweightCapableTreeStructure by lazy { WrappedTreeStructure(psi.containingFile) } + + private class WrappedTreeStructure(file: PsiFile) : FlyweightCapableTreeStructure { + private val lighterAST = TreeBackedLighterAST(file.node) + + private fun LighterASTNode.unwrap() = lighterAST.unwrap(this) + + override fun toString(node: LighterASTNode): CharSequence = node.unwrap().text + + override fun getRoot(): LighterASTNode = lighterAST.root + + override fun getParent(node: LighterASTNode): LighterASTNode? = node.unwrap().psi.parent?.node?.let { TreeBackedLighterAST.wrap(it) } + + override fun getChildren(node: LighterASTNode, nodesRef: Ref>): Int { + val children = node.unwrap().psi.children + if (children.isEmpty()) { + nodesRef.set(LighterASTNode.EMPTY_ARRAY) + } else { + nodesRef.set(children.map { TreeBackedLighterAST.wrap(it.node) }.toTypedArray()) + } + return children.size + } + + override fun disposeChildren(p0: Array?, p1: Int) { + } + + override fun getStartOffset(node: LighterASTNode): Int = node.unwrap().startOffset + + override fun getEndOffset(node: LighterASTNode): Int = node.unwrap().let { it.startOffset + it.textLength - 1 } + } } class FirRealPsiSourceElement(psi: P) : FirPsiSourceElement

(psi) { @@ -179,7 +213,7 @@ class FirFakeSourceElement(psi: P, override val kind: FirFak fun FirSourceElement.fakeElement(newKind: FirFakeSourceElementKind): FirSourceElement { return when (this) { - is FirLightSourceElement -> FirLightSourceElement(lighterASTNode, startOffset, endOffset, tree, newKind) + is FirLightSourceElement -> FirLightSourceElement(lighterASTNode, startOffset, endOffset, treeStructure, newKind) is FirPsiSourceElement<*> -> FirFakeSourceElement(psi, newKind) } } @@ -188,7 +222,7 @@ class FirLightSourceElement( override val lighterASTNode: LighterASTNode, override val startOffset: Int, override val endOffset: Int, - val tree: FlyweightCapableTreeStructure, + override val treeStructure: FlyweightCapableTreeStructure, override val kind: FirSourceElementKind = FirRealSourceElementKind, ) : FirSourceElement() { override val elementType: IElementType