K2: Update reference shortener to handle import alias

The existing reference shortener does not use import alias when it
shortens a symbol. Instead, it adds a new import directive for the
symbol that is already imported. This commit updates reference shortener
to let it reuse the existing import alias rather than adding a new one:

 1. When shortening a symbol, check whether the symbol is already
    imported.
 2. If it is already imported by an import alias, keep the symbol
    reference expression and the import alias as a string together in
    `ShortenCommand`.

The actual PSI update (shortening) based on the ShortenCommand is done
by IntelliJ.

^KTIJ-27205
This commit is contained in:
Jaebaek Seo
2023-10-03 12:19:24 -07:00
committed by teamcity
parent 02c12ae26f
commit e80f044847
24 changed files with 379 additions and 39 deletions
@@ -152,14 +152,41 @@ public interface KtReferenceShortenerMixIn : KtAnalysisSessionMixIn {
}
}
/**
* A class to keep a [KtUserType] to shorten and what shape the shortened result has to be. [shortenedReference] is the expected result of
* shortening in a string form. If [shortenedReference] is null, it means the shortening will simply delete the qualifier. Note that
* currently the only usage of [shortenedReference] is the case we have the import-alias. For example, [shortenedReference] will be
* "AliasType" when we shorten:
* ```
* import my.package.NewType as AliasType
* ... my.package.Ne<caret>wType ... // -> we can replace this with `AliasType`.
* ```
*/
public data class TypeToShortenInfo(val typeToShorten: SmartPsiElementPointer<KtUserType>, val shortenedReference: String?)
/**
* A class to keep a [KtDotQualifiedExpression] to shorten and what shape the shortened result has to be. [shortenedReference] is the
* expected result of shortening in a string form. If [shortenedReference] is null, it means the shortening will simply delete the
* qualifier. Note that currently the only usage of [shortenedReference] is the case we have the import-alias. For example,
* [shortenedReference] will be "bar" when we shorten:
* ```
* import my.package.foo as bar
* ... my.package.fo<caret>o ... // -> we can replace this with `bar`.
* ```
*/
public data class QualifierToShortenInfo(
val qualifierToShorten: SmartPsiElementPointer<KtDotQualifiedExpression>,
val shortenedReference: String?,
)
public interface ShortenCommand {
public val targetFile: SmartPsiElementPointer<KtFile>
public val importsToAdd: Set<FqName>
public val starImportsToAdd: Set<FqName>
public val typesToShorten: List<SmartPsiElementPointer<KtUserType>>
public val qualifiersToShorten: List<SmartPsiElementPointer<KtDotQualifiedExpression>>
public val listOfTypeToShortenInfo: List<TypeToShortenInfo>
public val listOfQualifierToShortenInfo: List<QualifierToShortenInfo>
public val kDocQualifiersToShorten: List<SmartPsiElementPointer<KDocName>>
public val isEmpty: Boolean
get() = typesToShorten.isEmpty() && qualifiersToShorten.isEmpty() && kDocQualifiersToShorten.isEmpty()
get() = listOfTypeToShortenInfo.isEmpty() && listOfQualifierToShortenInfo.isEmpty() && kDocQualifiersToShorten.isEmpty()
}
@@ -0,0 +1,12 @@
// FILE: main.kt
package test
import com.dependency.bar as bar1
import com.dependency.*
fun foo() = <expr>com.dependency.bar</expr>
// FILE: dependency.kt
package com.dependency
val bar = 3
@@ -0,0 +1,8 @@
Before shortening: com.dependency.bar
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] com.dependency.bar -> bar1
with SHORTEN_AND_IMPORT:
[qualifier] com.dependency.bar -> bar1
with SHORTEN_AND_STAR_IMPORT:
[qualifier] com.dependency.bar -> bar1
@@ -0,0 +1,11 @@
// FILE: main.kt
package test
import com.dependency.bar as bar1
fun foo() = <expr>com.dependency.bar()</expr>
// FILE: dependency.kt
package com.dependency
fun bar() = 3
@@ -0,0 +1,8 @@
Before shortening: com.dependency.bar()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] com.dependency.bar() -> bar1
with SHORTEN_AND_IMPORT:
[qualifier] com.dependency.bar() -> bar1
with SHORTEN_AND_STAR_IMPORT:
[qualifier] com.dependency.bar() -> bar1
@@ -0,0 +1,11 @@
// FILE: main.kt
package test
import com.dependency.bar as bar1
fun foo() = <expr>com.dependency.bar</expr>
// FILE: dependency.kt
package com.dependency
val bar = 3
@@ -0,0 +1,8 @@
Before shortening: com.dependency.bar
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] com.dependency.bar -> bar1
with SHORTEN_AND_IMPORT:
[qualifier] com.dependency.bar -> bar1
with SHORTEN_AND_STAR_IMPORT:
[qualifier] com.dependency.bar -> bar1
@@ -0,0 +1,11 @@
// FILE: main.kt
package test
import com.dependency.Bar as Bar1
fun foo(): <expr>com.dependency.Bar</expr> = Bar1()
// FILE: dependency.kt
package com.dependency
class Bar
@@ -0,0 +1,8 @@
Before shortening: com.dependency.Bar
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[type] com.dependency.Bar -> Bar1
with SHORTEN_AND_IMPORT:
[type] com.dependency.Bar -> Bar1
with SHORTEN_AND_STAR_IMPORT:
[type] com.dependency.Bar -> Bar1
@@ -0,0 +1,17 @@
// FILE: main.kt
package test
import com.dependency.Bar as Bar1
fun foo() = <expr>com.dependency.Bar.bar()</expr>
// FILE: dependency.kt
package com.dependency
class Bar {
companion object
}
fun Bar.bar(): Bar {
return this
}
@@ -0,0 +1,8 @@
Before shortening: com.dependency.Bar.bar()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] com.dependency.Bar -> Bar1
with SHORTEN_AND_IMPORT:
[qualifier] com.dependency.Bar -> Bar1
with SHORTEN_AND_STAR_IMPORT:
[qualifier] com.dependency.Bar -> Bar1
@@ -0,0 +1,20 @@
// FILE: main.kt
package test
import com.dependency.*
import com.dependency.bar as bar1
import com.dependency.bar as bar2
import com.dependency.bar as bar3
import com.dependency.bar
fun foo(a: Int) = <expr>when (a) {
1 -> bar1
2 -> bar2
3 -> bar3
else -> com.dependency.bar
}</expr>
// FILE: dependency.kt
package com.dependency
val bar = 3
@@ -0,0 +1,13 @@
Before shortening: when (a) {
1 -> bar1
2 -> bar2
3 -> bar3
else -> com.dependency.bar
}
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] com.dependency.bar -> bar1
with SHORTEN_AND_IMPORT:
[qualifier] com.dependency.bar -> bar1
with SHORTEN_AND_STAR_IMPORT:
[qualifier] com.dependency.bar -> bar1
@@ -0,0 +1,18 @@
// FILE: main.kt
package test
import com.dependency.bar as bar1
import com.dependency.bar as bar2
import com.dependency.bar as bar3
fun foo(a: Int) = <expr>when (a) {
1 -> bar1
2 -> com.dependency.bar
3 -> bar3
else -> com.dependency.bar
}</expr>
// FILE: dependency.kt
package com.dependency
val bar = 3
@@ -0,0 +1,16 @@
Before shortening: when (a) {
1 -> bar1
2 -> com.dependency.bar
3 -> bar3
else -> com.dependency.bar
}
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] com.dependency.bar -> bar1
[qualifier] com.dependency.bar -> bar1
with SHORTEN_AND_IMPORT:
[qualifier] com.dependency.bar -> bar1
[qualifier] com.dependency.bar -> bar1
with SHORTEN_AND_STAR_IMPORT:
[qualifier] com.dependency.bar -> bar1
[qualifier] com.dependency.bar -> bar1
@@ -0,0 +1,11 @@
// FILE: main.kt
package test
import com.dependency.*
fun foo() = <expr>com.dependency.bar()</expr>
// FILE: dependency.kt
package com.dependency
fun bar() = 3
@@ -0,0 +1,8 @@
Before shortening: com.dependency.bar()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] com.dependency.bar()
with SHORTEN_AND_IMPORT:
[qualifier] com.dependency.bar()
with SHORTEN_AND_STAR_IMPORT:
[qualifier] com.dependency.bar()