FIR checker: fix position strategy for UNRESOLVED_LABEL

This commit is contained in:
Tianyu Geng
2021-06-25 13:16:58 -07:00
committed by Ivan Kochurkin
parent 45d31fdba2
commit bcf6202863
24 changed files with 58 additions and 35 deletions
@@ -2,7 +2,7 @@
fun x() {} fun x() {}
operator fun Int.invoke(): Foo = <!UNRESOLVED_LABEL!>this@Foo<!> operator fun Int.invoke(): Foo = this<!UNRESOLVED_LABEL!>@Foo<!>
class Foo { class Foo {
@@ -96,7 +96,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val UNRESOLVED_REFERENCE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) { val UNRESOLVED_REFERENCE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
parameter<String>("reference") parameter<String>("reference")
} }
val UNRESOLVED_LABEL by error<PsiElement>() val UNRESOLVED_LABEL by error<PsiElement>(PositioningStrategy.LABEL)
val DESERIALIZATION_ERROR by error<PsiElement>() val DESERIALIZATION_ERROR by error<PsiElement>()
val ERROR_FROM_JAVA_RESOLUTION by error<PsiElement>() val ERROR_FROM_JAVA_RESOLUTION by error<PsiElement>()
val MISSING_STDLIB_CLASS by error<PsiElement>() val MISSING_STDLIB_CLASS by error<PsiElement>()
@@ -101,7 +101,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
UNREACHABLE_CODE, UNREACHABLE_CODE,
INLINE_PARAMETER_MODIFIER, INLINE_PARAMETER_MODIFIER,
ABSTRACT_MODIFIER, ABSTRACT_MODIFIER,
LABEL,
; ;
val expressionToCreate get() = "SourceElementPositioningStrategies.${strategy ?: name}" val expressionToCreate get() = "SourceElementPositioningStrategies.${strategy ?: name}"
@@ -127,7 +127,7 @@ object FirErrors {
// Unresolved // Unresolved
val INVISIBLE_REFERENCE by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val INVISIBLE_REFERENCE by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val UNRESOLVED_REFERENCE by error1<PsiElement, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) val UNRESOLVED_REFERENCE by error1<PsiElement, String>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val UNRESOLVED_LABEL by error0<PsiElement>() val UNRESOLVED_LABEL by error0<PsiElement>(SourceElementPositioningStrategies.LABEL)
val DESERIALIZATION_ERROR by error0<PsiElement>() val DESERIALIZATION_ERROR by error0<PsiElement>()
val ERROR_FROM_JAVA_RESOLUTION by error0<PsiElement>() val ERROR_FROM_JAVA_RESOLUTION by error0<PsiElement>()
val MISSING_STDLIB_CLASS by error0<PsiElement>() val MISSING_STDLIB_CLASS by error0<PsiElement>()
@@ -898,6 +898,18 @@ object LightTreePositioningStrategies {
return markElement(nodeToMark ?: node, startOffset, endOffset, tree, node) return markElement(nodeToMark ?: node, startOffset, endOffset, tree, node)
} }
} }
val LABEL: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
val nodeToMark = tree.findChildByType(node, KtNodeTypes.LABEL_QUALIFIER) ?: node
return markElement(nodeToMark, startOffset, endOffset, tree, node)
}
}
} }
fun FirSourceElement.hasValOrVar(): Boolean = fun FirSourceElement.hasValOrVar(): Boolean =
@@ -283,6 +283,11 @@ object SourceElementPositioningStrategies {
PositioningStrategies.ACTUAL_DECLARATION_NAME PositioningStrategies.ACTUAL_DECLARATION_NAME
) )
val LABEL = SourceElementPositioningStrategy(
LightTreePositioningStrategies.LABEL,
PositioningStrategies.LABEL
)
// TODO // TODO
val INCOMPATIBLE_DECLARATION = DEFAULT val INCOMPATIBLE_DECLARATION = DEFAULT
@@ -940,6 +940,12 @@ object PositioningStrategies {
} }
} }
val LABEL: PositioningStrategy<KtElement> = object : PositioningStrategy<KtElement>() {
override fun mark(element: KtElement): List<TextRange> {
return super.mark((element as? KtExpressionWithLabel)?.labelQualifier ?: element)
}
}
/** /**
* @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for * @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 * diagnostics on super and unresolved references. For example, with the following, only the part inside the parentheses should be
@@ -6,11 +6,11 @@ interface Trait {
class Outer : Trait { class Outer : Trait {
class Nested { class Nested {
val t = <!UNRESOLVED_LABEL!>this@Outer<!>.<!UNRESOLVED_REFERENCE!>bar<!>() val t = this<!UNRESOLVED_LABEL!>@Outer<!>.<!UNRESOLVED_REFERENCE!>bar<!>()
val s = super@Outer.<!UNRESOLVED_REFERENCE!>bar<!>() val s = super@Outer.<!UNRESOLVED_REFERENCE!>bar<!>()
inner class NestedInner { inner class NestedInner {
val t = <!UNRESOLVED_LABEL!>this@Outer<!>.<!UNRESOLVED_REFERENCE!>bar<!>() val t = this<!UNRESOLVED_LABEL!>@Outer<!>.<!UNRESOLVED_REFERENCE!>bar<!>()
val s = super@Outer.<!UNRESOLVED_REFERENCE!>bar<!>() val s = super@Outer.<!UNRESOLVED_REFERENCE!>bar<!>()
} }
} }
@@ -7,8 +7,8 @@ class Outer {
class Nested { class Nested {
fun f() = <!UNRESOLVED_REFERENCE!>function<!>() fun f() = <!UNRESOLVED_REFERENCE!>function<!>()
fun g() = <!UNRESOLVED_REFERENCE!>property<!> fun g() = <!UNRESOLVED_REFERENCE!>property<!>
fun h() = <!UNRESOLVED_LABEL!>this@Outer<!>.<!UNRESOLVED_REFERENCE!>function<!>() fun h() = this<!UNRESOLVED_LABEL!>@Outer<!>.<!UNRESOLVED_REFERENCE!>function<!>()
fun i() = <!UNRESOLVED_LABEL!>this@Outer<!>.<!UNRESOLVED_REFERENCE!>property<!> fun i() = this<!UNRESOLVED_LABEL!>@Outer<!>.<!UNRESOLVED_REFERENCE!>property<!>
} }
inner class Inner { inner class Inner {
@@ -1,17 +1,17 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE // !DIAGNOSTICS: -UNUSED_VARIABLE
val funLit = lambda@ fun String.() { val funLit = lambda@ fun String.() {
val d1 = <!UNRESOLVED_LABEL!>this@lambda<!> val d1 = this<!UNRESOLVED_LABEL!>@lambda<!>
} }
fun test() { fun test() {
val funLit = lambda@ fun String.(): <!UNRESOLVED_LABEL!>String<!> { val funLit = lambda@ fun String.(): <!UNRESOLVED_LABEL!>String<!> {
return <!UNRESOLVED_LABEL!>this@lambda<!> return this<!UNRESOLVED_LABEL!>@lambda<!>
} }
} }
fun lambda() { fun lambda() {
val funLit = lambda@ fun String.(): <!UNRESOLVED_LABEL!>String<!> { val funLit = lambda@ fun String.(): <!UNRESOLVED_LABEL!>String<!> {
return <!UNRESOLVED_LABEL!>this@lambda<!> return this<!UNRESOLVED_LABEL!>@lambda<!>
} }
} }
@@ -4,10 +4,10 @@ interface Iterator<out T> {
fun <R> map(transform: (element: T) -> R) : Iterator<R> = fun <R> map(transform: (element: T) -> R) : Iterator<R> =
object : Iterator<R> { object : Iterator<R> {
override fun next() : R = transform(<!UNRESOLVED_LABEL!>this@map<!>.<!UNRESOLVED_REFERENCE!>next<!>()) override fun next() : R = transform(this<!UNRESOLVED_LABEL!>@map<!>.<!UNRESOLVED_REFERENCE!>next<!>())
override val hasNext : Boolean override val hasNext : Boolean
// There's no 'this' associated with the map() function, only this of the Iterator class // There's no 'this' associated with the map() function, only this of the Iterator class
get() = <!UNRESOLVED_LABEL!>this@map<!>.<!UNRESOLVED_REFERENCE!>hasNext<!> get() = this<!UNRESOLVED_LABEL!>@map<!>.<!UNRESOLVED_REFERENCE!>hasNext<!>
} }
} }
@@ -7,7 +7,7 @@ open class Base<T>(p: Any?) {
class D: Base<Int>(1) { class D: Base<Int>(1) {
inner class B : Base<Int> { inner class B : Base<Int> {
constructor() : super(foo1(1)) constructor() : super(foo1(1))
constructor(x: Int) : super(<!UNRESOLVED_LABEL!>this@B<!>.<!UNRESOLVED_REFERENCE!>foo1<!>(1)) constructor(x: Int) : super(this<!UNRESOLVED_LABEL!>@B<!>.<!UNRESOLVED_REFERENCE!>foo1<!>(1))
constructor(x: Int, y: Int) : super(this@D.foo1(1)) constructor(x: Int, y: Int) : super(this@D.foo1(1))
} }
} }
@@ -7,6 +7,6 @@ fun Base.foo() {
class B : Base { class B : Base {
constructor() : super(foo1()) constructor() : super(foo1())
constructor(x: Int) : super(this@foo.foo1()) constructor(x: Int) : super(this@foo.foo1())
constructor(x: Int, y: Int) : super(<!UNRESOLVED_LABEL!>this@B<!>.<!UNRESOLVED_REFERENCE!>foo1<!>()) constructor(x: Int, y: Int) : super(this<!UNRESOLVED_LABEL!>@B<!>.<!UNRESOLVED_REFERENCE!>foo1<!>())
} }
} }
@@ -8,6 +8,6 @@ fun Base<Int>.foo() {
constructor() : super(foo1(<!ARGUMENT_TYPE_MISMATCH!>""<!>)) constructor() : super(foo1(<!ARGUMENT_TYPE_MISMATCH!>""<!>))
constructor(x: Int) : super(foo1(1)) constructor(x: Int) : super(foo1(1))
constructor(x: Int, y: Int) : super(this@foo.foo1(12)) constructor(x: Int, y: Int) : super(this@foo.foo1(12))
constructor(x: Int, y: Int, z: Int) : super(<!UNRESOLVED_LABEL!>this@B<!>.<!UNRESOLVED_REFERENCE!>foo1<!>("")) constructor(x: Int, y: Int, z: Int) : super(this<!UNRESOLVED_LABEL!>@B<!>.<!UNRESOLVED_REFERENCE!>foo1<!>(""))
} }
} }
@@ -9,7 +9,7 @@ class A {
{ {
<!ARGUMENT_TYPE_MISMATCH, TYPE_MISMATCH!><!UNRESOLVED_REFERENCE!>foo<!>() + <!ARGUMENT_TYPE_MISMATCH, TYPE_MISMATCH!><!UNRESOLVED_REFERENCE!>foo<!>() +
<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.<!UNRESOLVED_REFERENCE!>foo<!>() + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.<!UNRESOLVED_REFERENCE!>foo<!>() +
<!UNRESOLVED_LABEL!>this@A<!>.<!UNRESOLVED_REFERENCE!>foo<!>() + this<!UNRESOLVED_LABEL!>@A<!>.<!UNRESOLVED_REFERENCE!>foo<!>() +
<!UNRESOLVED_REFERENCE!>foobar<!>()<!> <!UNRESOLVED_REFERENCE!>foobar<!>()<!>
}) })
} }
@@ -6,7 +6,7 @@ class A {
fun foo() = 1 fun foo() = 1
constructor(x: Any?) constructor(x: Any?)
constructor() : this(object { constructor() : this(object {
fun bar() = <!UNRESOLVED_REFERENCE!>foo<!>() + <!UNRESOLVED_LABEL!>this@A<!>.<!UNRESOLVED_REFERENCE!>foo<!>() + fun bar() = <!UNRESOLVED_REFERENCE!>foo<!>() + this<!UNRESOLVED_LABEL!>@A<!>.<!UNRESOLVED_REFERENCE!>foo<!>() +
<!INAPPLICABLE_CANDIDATE!>foobar<!>() + super@A.<!UNRESOLVED_REFERENCE!>hashCode<!>() <!INAPPLICABLE_CANDIDATE!>foobar<!>() + super@A.<!UNRESOLVED_REFERENCE!>hashCode<!>()
}) })
} }
@@ -5,7 +5,7 @@ fun A.foobar() = 3
class A { class A {
fun foo() = 1 fun foo() = 1
constructor( x: Any = object { constructor( x: Any = object {
fun bar() = <!UNRESOLVED_REFERENCE!>foo<!>() + <!UNRESOLVED_LABEL!>this@A<!>.<!UNRESOLVED_REFERENCE!>foo<!>() + fun bar() = <!UNRESOLVED_REFERENCE!>foo<!>() + this<!UNRESOLVED_LABEL!>@A<!>.<!UNRESOLVED_REFERENCE!>foo<!>() +
<!INAPPLICABLE_CANDIDATE!>foobar<!>() <!INAPPLICABLE_CANDIDATE!>foobar<!>()
}) })
} }
@@ -3,6 +3,6 @@ fun foo(x: A) = 1
class A { class A {
constructor(x: Int) constructor(x: Int)
constructor(x: Int, y: Int, z: Int = x + foo(<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>) + foo(<!UNRESOLVED_LABEL!>this@A<!>)) : constructor(x: Int, y: Int, z: Int = x + foo(<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>) + foo(this<!UNRESOLVED_LABEL!>@A<!>)) :
this(x + foo(<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>) + foo(<!UNRESOLVED_LABEL!>this@A<!>)) this(x + foo(<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>) + foo(this<!UNRESOLVED_LABEL!>@A<!>))
} }
@@ -10,6 +10,6 @@ class A {
<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.foobar() + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.foobar() +
<!UNRESOLVED_REFERENCE!>prop<!> + <!UNRESOLVED_REFERENCE!>prop<!> +
<!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.prop + <!INSTANCE_ACCESS_BEFORE_SUPER_CALL!>this<!>.prop +
<!UNRESOLVED_LABEL!>this@A<!>.prop<!> this<!UNRESOLVED_LABEL!>@A<!>.prop<!>
) )
} }
@@ -2,11 +2,11 @@
class A() { class A() {
fun foo() : Unit { fun foo() : Unit {
this@A this@A
<!UNRESOLVED_LABEL!>this@a<!> this<!UNRESOLVED_LABEL!>@a<!>
this this
} }
val x = this@A.foo() val x = this@A.foo()
val y = this.foo() val y = this.foo()
val z = foo() val z = foo()
} }
@@ -11,8 +11,8 @@ class A(val a:Int) {
checkSubtype<A>(this@A) checkSubtype<A>(this@A)
} }
val b: Double.() -> Unit = a@{ checkSubtype<Double>(this@a) + checkSubtype<Byte>(this@xx) } val b: Double.() -> Unit = a@{ checkSubtype<Double>(this@a) + checkSubtype<Byte>(this@xx) }
val c = a@{ -> <!UNRESOLVED_LABEL!>this@a<!> + checkSubtype<Byte>(this@xx) } val c = a@{ -> this<!UNRESOLVED_LABEL!>@a<!> + checkSubtype<Byte>(this@xx) }
return (a@{checkSubtype<Double>(this@a) + checkSubtype<Byte>(this@xx)}) return (a@{checkSubtype<Double>(this@a) + checkSubtype<Byte>(this@xx)})
} }
} }
} }
@@ -3,6 +3,6 @@ interface Base {
} }
val String.test: Base = <!EXTENSION_PROPERTY_WITH_BACKING_FIELD!>object<!>: Base { val String.test: Base = <!EXTENSION_PROPERTY_WITH_BACKING_FIELD!>object<!>: Base {
override fun foo() { override fun foo() {
<!UNRESOLVED_LABEL!>this@test<!> this<!UNRESOLVED_LABEL!>@test<!>
} }
} }
@@ -1,4 +1,4 @@
fun foo1() : Unit { fun foo1() : Unit {
<!NO_THIS!>this<!> <!NO_THIS!>this<!>
<!UNRESOLVED_LABEL!>this@a<!> this<!UNRESOLVED_LABEL!>@a<!>
} }
@@ -10,13 +10,13 @@ class Foo {
inner class Bar { inner class Bar {
fun good() { fun good() {
contract { contract {
<!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_LABEL!>this@Bar<!> != null)<!> <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (this<!UNRESOLVED_LABEL!>@Bar<!> != null)<!>
} }
} }
fun badOuter() { fun badOuter() {
contract { contract {
<!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_LABEL!>this@Foo<!> != null)<!> <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (this<!UNRESOLVED_LABEL!>@Foo<!> != null)<!>
} }
} }
@@ -34,7 +34,7 @@ class Foo {
fun A?.badWithReceiver() { fun A?.badWithReceiver() {
contract { contract {
<!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (<!UNRESOLVED_LABEL!>this@Bar<!> != null)<!> <!ERROR_IN_CONTRACT_DESCRIPTION!>returns() implies (this<!UNRESOLVED_LABEL!>@Bar<!> != null)<!>
} }
} }
} }