[FIR][LightTree] More fixes in diagnostic positioning

Keep tree padding for modifiers
More REFERENCE_EXPRESSIONS kinds
Fix source for some call expressions
This commit is contained in:
Andrey Zinovyev
2021-04-19 14:36:55 +03:00
committed by TeamCityServer
parent f3dc8dfb21
commit 0a68edf3bd
11 changed files with 50 additions and 21 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis package org.jetbrains.kotlin.fir.analysis
import com.intellij.lang.LighterASTNode
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 org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
@@ -37,7 +38,13 @@ private fun FirPsiSourceElement<*>.getChild(types: Set<IElementType>, index: Int
private fun FirLightSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int): FirSourceElement? { private fun FirLightSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int): FirSourceElement? {
val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth) val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth)
val childNode = visitor.find(lighterASTNode) ?: return null val childNode = visitor.find(lighterASTNode) ?: return null
//we need to keep 'padding' of parent node in child node return buildChildSourceElement(childNode)
}
/**
* Keeps 'padding' of parent node in child node
*/
internal fun FirLightSourceElement.buildChildSourceElement(childNode: LighterASTNode): FirLightSourceElement {
val offsetDelta = startOffset - lighterASTNode.startOffset val offsetDelta = startOffset - lighterASTNode.startOffset
return childNode.toFirLightSourceElement( return childNode.toFirLightSourceElement(
treeStructure, treeStructure,
@@ -34,14 +34,15 @@ internal sealed class FirModifierList {
class FirLightModifierList( class FirLightModifierList(
val modifierList: LighterASTNode, val modifierList: LighterASTNode,
val tree: FlyweightCapableTreeStructure<LighterASTNode> val tree: FlyweightCapableTreeStructure<LighterASTNode>,
private val offsetDelta: Int
) : FirModifierList() { ) : FirModifierList() {
override val modifiers: List<FirModifier.FirLightModifier> override val modifiers: List<FirModifier.FirLightModifier>
get() { get() {
val modifierNodes = modifierList.getChildren(tree) val modifierNodes = modifierList.getChildren(tree)
return modifierNodes.filterNotNull() return modifierNodes.filterNotNull()
.filter { it.tokenType is KtModifierKeywordToken } .filter { it.tokenType is KtModifierKeywordToken }
.map { FirModifier.FirLightModifier(it, it.tokenType as KtModifierKeywordToken, tree) } .map { FirModifier.FirLightModifier(it, it.tokenType as KtModifierKeywordToken, tree, offsetDelta) }
} }
} }
@@ -65,10 +66,15 @@ internal sealed class FirModifier<Node : Any>(val node: Node, val token: KtModif
class FirLightModifier( class FirLightModifier(
node: LighterASTNode, node: LighterASTNode,
token: KtModifierKeywordToken, token: KtModifierKeywordToken,
val tree: FlyweightCapableTreeStructure<LighterASTNode> val tree: FlyweightCapableTreeStructure<LighterASTNode>,
private val offsetDelta: Int
) : FirModifier<LighterASTNode>(node, token) { ) : FirModifier<LighterASTNode>(node, token) {
override val source: FirSourceElement override val source: FirSourceElement
get() = node.toFirLightSourceElement(tree) get() = node.toFirLightSourceElement(
tree,
startOffset = node.startOffset + offsetDelta,
endOffset = node.endOffset + offsetDelta
)
} }
abstract val source: FirSourceElement abstract val source: FirSourceElement
@@ -81,7 +87,8 @@ internal fun FirSourceElement?.getModifierList(): FirModifierList? {
is FirLightSourceElement -> { is FirLightSourceElement -> {
val modifierListNode = lighterASTNode.getChildren(treeStructure).find { it?.tokenType == KtNodeTypes.MODIFIER_LIST } val modifierListNode = lighterASTNode.getChildren(treeStructure).find { it?.tokenType == KtNodeTypes.MODIFIER_LIST }
?: return null ?: return null
FirModifierList.FirLightModifierList(modifierListNode, treeStructure) val offsetDelta = startOffset - lighterASTNode.startOffset
FirModifierList.FirLightModifierList(modifierListNode, treeStructure, offsetDelta)
} }
} }
} }
@@ -20,6 +20,7 @@ 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.stubs.elements.KtConstantExpressionElementType
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
object LightTreePositioningStrategies { object LightTreePositioningStrategies {
@@ -625,6 +626,9 @@ private val REFERENCE_EXPRESSIONS = setOf(
KtNodeTypes.CONSTRUCTOR_DELEGATION_REFERENCE, KtNodeTypes.CONSTRUCTOR_DELEGATION_REFERENCE,
KtNodeTypes.SUPER_EXPRESSION, KtNodeTypes.SUPER_EXPRESSION,
KtNodeTypes.ARRAY_ACCESS_EXPRESSION, KtNodeTypes.ARRAY_ACCESS_EXPRESSION,
KtNodeTypes.CALL_EXPRESSION,
KtNodeTypes.LABELED_EXPRESSION,
KtNodeTypes.DOT_QUALIFIED_EXPRESSION,
KtNodeTypes.FUN, KtNodeTypes.FUN,
) )
@@ -648,7 +652,9 @@ 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 REFERENCE_EXPRESSIONS || it?.tokenType == KtNodeTypes.PARENTHESIZED it?.tokenType in REFERENCE_EXPRESSIONS ||
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)
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.stubs.elements.KtFunctionElementType
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
abstract class BaseConverter( abstract class BaseConverter(
@@ -81,6 +80,15 @@ abstract class BaseConverter(
return null return null
} }
protected fun LighterASTNode.getFirstChildExpressionUnwrapped(): LighterASTNode? {
val expression = getFirstChildExpression() ?: return null
return if (expression.tokenType == KtNodeTypes.PARENTHESIZED) {
expression.getFirstChildExpressionUnwrapped()
} else {
expression
}
}
private fun LighterASTNode.getLastChildExpression(): LighterASTNode? { private fun LighterASTNode.getLastChildExpression(): LighterASTNode? {
var result: LighterASTNode? = null var result: LighterASTNode? = null
forEachChildren { forEachChildren {
@@ -548,7 +548,7 @@ class ExpressionsConverter(
val (calleeReference, explicitReceiver, isImplicitInvoke) = when { val (calleeReference, explicitReceiver, isImplicitInvoke) = when {
name != null -> CalleeAndReceiver( name != null -> CalleeAndReceiver(
buildSimpleNamedReference { buildSimpleNamedReference {
this.source = source this.source = callSuffix.getFirstChildExpressionUnwrapped()?.toFirSourceElement() ?: source
this.name = name.nameAsSafeName() this.name = name.nameAsSafeName()
} }
) )
@@ -4,7 +4,8 @@ package h
class Square() { class Square() {
var size : Double = var size : Double =
<!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) { <!UNRESOLVED_REFERENCE!>set<!>(<!UNRESOLVED_REFERENCE!>value<!>) {
<!SYNTAX!>$area<!> <!SYNTAX!>= size * size<!> //in LT this LAMBDA_EXPRESSION get parsed lazyly, but doesn't got anywhere in FIR tree (as property doesn't have place for it)
<!SYNTAX{PSI}!>$area<!> <!SYNTAX{PSI}!>= size * size<!>
} }
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var area : Double<!> <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>var area : Double<!>
@@ -6,9 +6,9 @@ enum class Enum {
<!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!> <!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!>
<!NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!> <!LOCAL_INTERFACE_NOT_ALLOWED, NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!>
object TestObject <!LOCAL_OBJECT_NOT_ALLOWED!>object TestObject<!>
enum class TestEnumClass { enum class TestEnumClass {
OTHER_ENTRY OTHER_ENTRY
@@ -6,9 +6,9 @@ enum class Enum {
<!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!> <!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!>
<!NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!> <!LOCAL_INTERFACE_NOT_ALLOWED, NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!>
object TestObject <!LOCAL_OBJECT_NOT_ALLOWED!>object TestObject<!>
enum class TestEnumClass { enum class TestEnumClass {
OTHER_ENTRY OTHER_ENTRY
@@ -6,9 +6,9 @@ enum class Enum {
<!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!> <!NESTED_CLASS_NOT_ALLOWED!>class TestNested<!>
<!NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!> <!LOCAL_INTERFACE_NOT_ALLOWED, NESTED_CLASS_NOT_ALLOWED!>interface TestInterface<!>
object TestObject <!LOCAL_OBJECT_NOT_ALLOWED!>object TestObject<!>
enum class TestEnumClass { enum class TestEnumClass {
OTHER_ENTRY OTHER_ENTRY
+3 -3
View File
@@ -6,13 +6,13 @@ package toplevelObjectDeclarations
<!NO_VALUE_FOR_PARAMETER!>class T : <!SUPERTYPE_NOT_INITIALIZED!>Foo<!> {}<!> <!NO_VALUE_FOR_PARAMETER!>class T : <!SUPERTYPE_NOT_INITIALIZED!>Foo<!> {}<!>
object A : <!SUPERTYPE_NOT_INITIALIZED!>Foo<!> { <!NO_VALUE_FOR_PARAMETER{LT}!>object A : <!SUPERTYPE_NOT_INITIALIZED!>Foo<!> {
val x : Int = 2 val x : Int = 2
fun test() : Int { fun test() : Int {
return x + foo(<!NO_VALUE_FOR_PARAMETER!>)<!> return x + foo(<!NO_VALUE_FOR_PARAMETER{PSI}!>)<!>
} }
} }<!>
object B : A {} object B : A {}
@@ -25,5 +25,5 @@ val z = z
fun block(f : () -> Unit) = f() fun block(f : () -> Unit) = f()
fun bar3() = block{ <!UNRESOLVED_REFERENCE!>foo3<!>() // <-- missing closing curly bracket fun bar3() = block{ <!UNRESOLVED_REFERENCE!>foo3<!>() // <-- missing closing curly bracket
fun foo3() = block{ bar3() }<!SYNTAX!><!> fun foo3() = block{ bar3() }<!SYNTAX{PSI}!><!>