KT-62675 [AA] Handle labeled this expressions in reference shortener

At the moment, there is no good way to meaningfully filter `this`
expressions. The filters for the reference shortener can work only with
symbols, and it does not make a lot of sense to check any particular
symbol when deciding whether to shorten a labeled `this` expression.

We would probably need a better API for the shortener to be able
to filter more precisely (see KT-63555)

^KT-62675 Fixed
This commit is contained in:
Roman Golyshev
2023-11-06 12:17:13 +01:00
committed by teamcity
parent d47557067c
commit 4f5926a88f
23 changed files with 393 additions and 8 deletions
@@ -18,19 +18,23 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.kotlin.psi.KtUserType
/**
* @property removeThis If set to `true`, reference shortener will detect redundant `this` qualifiers
* and will collect them to [ShortenCommand.qualifiersToShorten].
* and will collect them to [ShortenCommand.listOfQualifierToShortenInfo].
* @property removeThisLabels If set to `true`, reference shortener will detect redundant labels on `this` expressions,
* and will collect them to [ShortenCommand.thisLabelsToShorten]
*/
public data class ShortenOptions(
public val removeThis: Boolean = false,
public val removeThisLabels: Boolean = false,
) {
public companion object {
public val DEFAULT: ShortenOptions = ShortenOptions()
public val ALL_ENABLED: ShortenOptions = ShortenOptions(removeThis = true)
public val ALL_ENABLED: ShortenOptions = ShortenOptions(removeThis = true, removeThisLabels = true)
}
}
@@ -179,14 +183,26 @@ public data class QualifierToShortenInfo(
val shortenedReference: String?,
)
/**
* A class with a reference to [KtThisExpression] with a label qualifier ([KtThisExpression.labelQualifier]) that can be safely removed
* without changing the semantics of the code.
*/
public data class ThisLabelToShortenInfo(
val labelToShorten: SmartPsiElementPointer<KtThisExpression>,
)
public interface ShortenCommand {
public val targetFile: SmartPsiElementPointer<KtFile>
public val importsToAdd: Set<FqName>
public val starImportsToAdd: Set<FqName>
public val listOfTypeToShortenInfo: List<TypeToShortenInfo>
public val listOfQualifierToShortenInfo: List<QualifierToShortenInfo>
public val thisLabelsToShorten: List<ThisLabelToShortenInfo>
public val kDocQualifiersToShorten: List<SmartPsiElementPointer<KDocName>>
public val isEmpty: Boolean
get() = listOfTypeToShortenInfo.isEmpty() && listOfQualifierToShortenInfo.isEmpty() && kDocQualifiersToShorten.isEmpty()
get() = listOfTypeToShortenInfo.isEmpty() &&
listOfQualifierToShortenInfo.isEmpty() &&
thisLabelsToShorten.isEmpty() &&
kDocQualifiersToShorten.isEmpty()
}
@@ -0,0 +1,9 @@
package test
class Regular {
fun one() {}
}
fun Regular.usage() {
<expr>this@usage.one()</expr>
}
@@ -0,0 +1,11 @@
Before shortening: this@usage.one()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] this@usage.one()
[thisLabel] this@usage
with SHORTEN_AND_IMPORT:
[qualifier] this@usage.one()
[thisLabel] this@usage
with SHORTEN_AND_STAR_IMPORT:
[qualifier] this@usage.one()
[thisLabel] this@usage
@@ -0,0 +1,13 @@
package test
class Regular {
fun one() {}
}
fun test(action: Regular.() -> Unit) {}
fun Regular.usage() {
test {
<expr>this@usage.one()</expr>
}
}
@@ -0,0 +1,5 @@
Before shortening: this@usage.one()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
with SHORTEN_AND_STAR_IMPORT:
@@ -0,0 +1,11 @@
package test
class Regular {
fun one() {}
}
fun Regular.usage() {
fun Regular.local() {
<expr>this@usage.one()</expr>
}
}
@@ -0,0 +1,5 @@
Before shortening: this@usage.one()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
with SHORTEN_AND_STAR_IMPORT:
@@ -0,0 +1,13 @@
package test
class Regular {
fun one() {}
}
fun test(action: Regular.() -> Unit) {}
fun usage() {
test {
<expr>this@test.one()</expr>
}
}
@@ -0,0 +1,11 @@
Before shortening: this@test.one()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] this@test.one()
[thisLabel] this@test
with SHORTEN_AND_IMPORT:
[qualifier] this@test.one()
[thisLabel] this@test
with SHORTEN_AND_STAR_IMPORT:
[qualifier] this@test.one()
[thisLabel] this@test
@@ -0,0 +1,15 @@
package test
class Regular {
fun one() {}
}
fun test(action: Regular.() -> Unit) {}
fun usage() {
test {
test r2@{
<expr>this@test.one()</expr>
}
}
}
@@ -0,0 +1,5 @@
Before shortening: this@test.one()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
with SHORTEN_AND_STAR_IMPORT:
@@ -0,0 +1,9 @@
package test
class Regular {
fun one() {}
fun usage() {
<expr>this@Regular.one()</expr>
}
}
@@ -0,0 +1,11 @@
Before shortening: this@Regular.one()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] this@Regular.one()
[thisLabel] this@Regular
with SHORTEN_AND_IMPORT:
[qualifier] this@Regular.one()
[thisLabel] this@Regular
with SHORTEN_AND_STAR_IMPORT:
[qualifier] this@Regular.one()
[thisLabel] this@Regular
@@ -0,0 +1,13 @@
package test
class Other {
fun one() {}
}
class Regular {
fun one() {}
fun Other.usage() {
<expr>this@Regular.one()</expr>
}
}
@@ -0,0 +1,5 @@
Before shortening: this@Regular.one()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
with SHORTEN_AND_STAR_IMPORT:
@@ -0,0 +1,11 @@
package test
class Regular {
fun one() {}
inner class Inner {
fun usage() {
<expr>this@Regular.one()</expr>
}
}
}
@@ -0,0 +1,5 @@
Before shortening: this@Regular.one()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
with SHORTEN_AND_STAR_IMPORT: