Skip to content

Commit 39fef62

Browse files
akozlovaSpace Team
authored and
Space Team
committed
[AA] support `#isReferenceToImportAlias for all fir references
- reference on constructor through import alias: reference in import directive resolves to class, thus we have to check constructor explicitly ^KT-68272 fixed - references in kdoc, etc. have to support import aliases explicitly ^KT-68273 fixed
1 parent ab0ca37 commit 39fef62

File tree

21 files changed

+146
-46
lines changed

21 files changed

+146
-46
lines changed

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
1616
import org.jetbrains.kotlin.fir.expressions.FirLoopJump
1717
import org.jetbrains.kotlin.fir.psi
1818
import org.jetbrains.kotlin.psi.*
19-
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
2019

2120
internal class KaFirSimpleNameReference(
2221
expression: KtSimpleNameExpression,
@@ -42,7 +41,7 @@ internal class KaFirSimpleNameReference(
4241
}
4342

4443
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
45-
return getImportAlias(alias.importDirective) != null
44+
return super<KaFirReference>.isReferenceToImportAlias(alias)
4645
}
4746

4847
override fun KaSession.resolveToSymbols(): Collection<KaSymbol> {
@@ -85,31 +84,6 @@ internal class KaFirSimpleNameReference(
8584
return false
8685
}
8786

88-
private fun getImportAlias(importDirective: KtImportDirective?): KtImportAlias? {
89-
val fqName = importDirective?.importedFqName ?: return null
90-
val codeFragment = KtPsiFactory(element.project).createExpressionCodeFragment(fqName.asString(), element)
91-
val contentElement = codeFragment.getContentElement()
92-
val importResults =
93-
when (contentElement) {
94-
is KtDotQualifiedExpression -> contentElement.selectorExpression?.mainReference?.multiResolve(false)
95-
is KtSimpleNameExpression -> contentElement.mainReference.multiResolve(false)
96-
else -> null
97-
} ?: return null
98-
val resolveResults = multiResolve(false)
99-
if (resolveResults.any { it in importResults }) {
100-
return importDirective.alias
101-
}
102-
val targets = resolveResults.mapNotNull { it.element }
103-
val adjustedImportTargets = importResults.mapNotNull {
104-
val e = it.element
105-
if (e is KtObjectDeclaration && e.isCompanion()) e.containingClassOrObject else null
106-
}
107-
if (adjustedImportTargets.any { it in targets }) {
108-
return importDirective.alias
109-
}
110-
return null
111-
}
112-
11387
override fun getImportAlias(): KtImportAlias? {
11488
val name = element.getReferencedName()
11589
val file = element.containingKtFile

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirArrayAccessReference.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
1414
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
1515
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
1616
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
17+
import org.jetbrains.kotlin.psi.KtImportAlias
1718

1819
class KaFirArrayAccessReference(
1920
expression: KtArrayAccessExpression
@@ -27,4 +28,9 @@ class KaFirArrayAccessReference(
2728
else -> emptyList()
2829
}
2930
}
31+
32+
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
33+
return super<KaFirReference>.isReferenceToImportAlias(alias)
34+
}
35+
3036
}

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirCollectionLiteralReference.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType
1717
import org.jetbrains.kotlin.fir.types.resolvedType
1818

1919
import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression
20+
import org.jetbrains.kotlin.psi.KtImportAlias
2021

2122
class KaFirCollectionLiteralReference(
2223
expression: KtCollectionLiteralExpression
@@ -29,4 +30,8 @@ class KaFirCollectionLiteralReference(
2930
val call = arrayTypeToArrayOfCall[type.lookupTag.classId] ?: arrayOf
3031
return listOfNotNull(arrayOfSymbol(call))
3132
}
33+
34+
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
35+
return super<KaFirReference>.isReferenceToImportAlias(alias)
36+
}
3237
}

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirConstructorDelegationReference.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.api.KaSession
1212
import org.jetbrains.kotlin.analysis.api.fir.KaFirSession
1313
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
1414
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
15+
import org.jetbrains.kotlin.psi.KtImportAlias
1516

1617
class KaFirConstructorDelegationReference(
1718
expression: KtConstructorDelegationReferenceExpression
@@ -22,4 +23,8 @@ class KaFirConstructorDelegationReference(
2223
val fir = expression.getOrBuildFirSafe<FirDelegatedConstructorCall>(firResolveSession) ?: return emptyList()
2324
return listOfNotNull(fir.calleeReference.getResolvedKtSymbolOfNameReference(firSymbolBuilder))
2425
}
26+
27+
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
28+
return super<KaFirReference>.isReferenceToImportAlias(alias)
29+
}
2530
}

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirDestructuringDeclarationReference.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.analysis.api.fir.KaFirSession
1414
import org.jetbrains.kotlin.analysis.api.fir.buildSymbol
1515
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
1616
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
17+
import org.jetbrains.kotlin.psi.KtImportAlias
1718

1819
class KaFirDestructuringDeclarationReference(
1920
element: KtDestructuringDeclarationEntry
@@ -33,4 +34,9 @@ class KaFirDestructuringDeclarationReference(
3334
val componentFunctionSymbol = (fir.initializer as? FirComponentCall)?.getCalleeSymbol() ?: return null
3435
return componentFunctionSymbol.fir.buildSymbol(firSymbolBuilder)
3536
}
37+
38+
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
39+
return super<KaFirReference>.isReferenceToImportAlias(alias)
40+
}
41+
3642
}

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirForLoopInReference.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.analysis.api.fir.KaFirSession
1616
import org.jetbrains.kotlin.analysis.api.fir.buildSymbol
1717
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
1818
import org.jetbrains.kotlin.psi.KtForExpression
19+
import org.jetbrains.kotlin.psi.KtImportAlias
1920

2021
open class KaFirForLoopInReference(expression: KtForExpression) : KtForLoopInReference(expression), KaFirReference {
2122
override fun KaSession.resolveToSymbols(): Collection<KaSymbol> {
@@ -37,4 +38,9 @@ open class KaFirForLoopInReference(expression: KtForExpression) : KtForLoopInRef
3738

3839
private fun FirProperty.getInitializerFunctionCall() =
3940
(initializer as? FirFunctionCall)?.calleeReference?.getResolvedSymbolOfNameReference()
41+
42+
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
43+
return super<KaFirReference>.isReferenceToImportAlias(alias)
44+
}
45+
4046
}

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirInvokeFunctionReference.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.api.calls.symbol
1212
import org.jetbrains.kotlin.analysis.api.symbols.KaFunctionSymbol
1313
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
1414
import org.jetbrains.kotlin.psi.KtCallExpression
15+
import org.jetbrains.kotlin.psi.KtImportAlias
1516

1617
class KaFirInvokeFunctionReference(expression: KtCallExpression) : KtInvokeFunctionReference(expression), KaFirReference {
1718
override fun KaSession.resolveToSymbols(): Collection<KaSymbol> {
@@ -23,4 +24,8 @@ class KaFirInvokeFunctionReference(expression: KtCallExpression) : KtInvokeFunct
2324
?.takeUnless { it is KaFunctionSymbol && it.isBuiltinFunctionInvoke }
2425
}
2526
}
27+
28+
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
29+
return super<KaFirReference>.isReferenceToImportAlias(alias)
30+
}
2631
}

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirKDocReference.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.idea.references.KDocReference
1414
import org.jetbrains.kotlin.idea.references.KaFirReference
1515
import org.jetbrains.kotlin.idea.references.getPsiDeclarations
1616
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
17+
import org.jetbrains.kotlin.psi.KtImportAlias
1718

1819
internal class KaFirKDocReference(element: KDocName) : KDocReference(element), KaFirReference {
1920
override fun KaSession.resolveToSymbols(): Collection<KaSymbol> {
@@ -34,4 +35,9 @@ internal class KaFirKDocReference(element: KDocName) : KDocReference(element), K
3435
}
3536
}
3637
}
38+
39+
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
40+
return super<KaFirReference>.isReferenceToImportAlias(alias)
41+
}
42+
3743
}

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirPropertyDelegationMethodsReference.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.analysis.api.fir.KaFirSession
1717
import org.jetbrains.kotlin.analysis.api.fir.buildSymbol
1818
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
1919
import org.jetbrains.kotlin.psi.KtElement
20+
import org.jetbrains.kotlin.psi.KtImportAlias
2021
import org.jetbrains.kotlin.psi.KtPropertyDelegate
2122

2223
class KtFirPropertyDelegationMethodsReference(
@@ -36,4 +37,9 @@ class KtFirPropertyDelegationMethodsReference(
3637

3738
private inline fun <reified S : FirStatement> FirPropertyAccessor.singleStatementOfType(): S? =
3839
body?.statements?.singleOrNull() as? S
40+
41+
override fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
42+
return super<KaFirReference>.isReferenceToImportAlias(alias)
43+
}
44+
3945
}

analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KtFirReference.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ import com.intellij.psi.PsiElement
99
import org.jetbrains.kotlin.analysis.api.KaSession
1010
import org.jetbrains.kotlin.analysis.api.KaSymbolBasedReference
1111
import org.jetbrains.kotlin.analysis.api.fir.findReferencePsi
12+
import org.jetbrains.kotlin.psi.KtClass
13+
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
14+
import org.jetbrains.kotlin.psi.KtImportAlias
15+
import org.jetbrains.kotlin.psi.KtImportDirective
16+
import org.jetbrains.kotlin.psi.KtObjectDeclaration
17+
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
18+
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
1219
import org.jetbrains.kotlin.analysis.api.fir.symbols.KaFirSymbol
1320
import org.jetbrains.kotlin.analysis.api.symbols.KaCallableSymbol
1421
import org.jetbrains.kotlin.analysis.api.symbols.KaSymbol
@@ -31,6 +38,33 @@ interface KaFirReference : KtReference, KaSymbolBasedReference {
3138
}
3239

3340
override val resolver get() = KaFirReferenceResolver
41+
42+
fun isReferenceToImportAlias(alias: KtImportAlias): Boolean {
43+
return getImportAlias(alias.importDirective) != null
44+
}
45+
46+
fun getImportAlias(importDirective: KtImportDirective?): KtImportAlias? {
47+
val importedReference = importDirective?.importedReference ?: return null
48+
val importResults =
49+
when (importedReference) {
50+
is KtDotQualifiedExpression -> importedReference.selectorExpression?.mainReference?.multiResolve(false)
51+
is KtSimpleNameExpression -> importedReference.mainReference.multiResolve(false)
52+
else -> null
53+
} ?: return null
54+
val targets = multiResolve(false).mapNotNull { it.element }
55+
val adjustedImportTargets = importResults.mapNotNull { it.element }
56+
val manager = importDirective.manager
57+
if (adjustedImportTargets.any { importTarget ->
58+
targets.any { target ->
59+
manager.areElementsEquivalent(target, importTarget) ||
60+
target.isConstructorOf(importTarget) ||
61+
importTarget is KtObjectDeclaration && importTarget.isCompanion() && importTarget.getNonStrictParentOfType<KtClass>() == target
62+
}
63+
}) {
64+
return importDirective.alias
65+
}
66+
return null
67+
}
3468
}
3569

3670
internal fun KaSession.getPsiDeclarations(symbol: KaFirSymbol<*>): Collection<PsiElement> {

analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceImportAliasTestGenerated.java

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/references/AbstractReferenceImportAliasTest.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.references
88
import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedTest
99
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtTestModule
1010
import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider
11-
import org.jetbrains.kotlin.idea.references.mainReference
1211
import org.jetbrains.kotlin.psi.KtFile
13-
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
1412
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
1513
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
14+
import org.jetbrains.kotlin.test.directives.model.singleValue
1615
import org.jetbrains.kotlin.test.services.TestServices
1716
import org.jetbrains.kotlin.test.services.assertions
17+
import kotlin.test.assertNotNull
1818

1919
abstract class AbstractReferenceImportAliasTest : AbstractAnalysisApiBasedTest() {
2020
override fun configureTest(builder: TestConfigurationBuilder) {
@@ -25,10 +25,15 @@ abstract class AbstractReferenceImportAliasTest : AbstractAnalysisApiBasedTest()
2525
}
2626

2727
override fun doTestByMainFile(mainFile: KtFile, mainModule: KtTestModule, testServices: TestServices) {
28-
val element = testServices.expressionMarkerProvider.getElementOfTypeAtCaret<KtSimpleNameExpression>(mainFile)
29-
val alias = element.mainReference.getImportAlias()
30-
val expectedAlias = mainModule.testModule.directives[Directives.TYPE_ALIAS].joinToString(" ")
31-
testServices.assertions.assertEquals(expectedAlias, alias?.text)
28+
val position = testServices.expressionMarkerProvider.getCaretPosition(mainFile)
29+
val reference = mainFile.findReferenceAt(position)
30+
assertNotNull(reference)
31+
val expectedAlias = mainModule.testModule.directives.singleValue(Directives.TYPE_ALIAS)
32+
val importDirective = mainFile.importDirectives.find { it.aliasName == expectedAlias }
33+
assertNotNull(importDirective)
34+
val importAlias = importDirective.alias
35+
assertNotNull(importAlias)
36+
testServices.assertions.assertTrue(reference.isReferenceTo(importAlias))
3237
}
3338

3439
private object Directives : SimpleDirectivesContainer() {

analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceImportAliasTestGenerated.java

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

analysis/analysis-api/testData/imports/importAliases/classAlias.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// TYPE_ALIAS: as bar
1+
// TYPE_ALIAS: bar
22
import Foo as bar
33

44
object Foo {

analysis/analysis-api/testData/imports/importAliases/classAliasWithCompanionObject.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// TYPE_ALIAS: as bar
1+
// TYPE_ALIAS: bar
22
import Foo as bar
33

44
class Foo {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// TYPE_ALIAS: bar
2+
import Foo as bar
3+
4+
class Foo() {
5+
constructor(i: Int): this()
6+
}
7+
8+
fun test() {
9+
val foo = ba<caret>r()
10+
}

analysis/analysis-api/testData/imports/importAliases/functionAlias.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// TYPE_ALIAS: as bar
1+
// TYPE_ALIAS: bar
22
import Foo.foo as bar
33

44
object Foo {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// TYPE_ALIAS: bar
2+
import Foo as bar
3+
4+
/**
5+
* [ba<caret>r]
6+
*/
7+
object Foo {
8+
}

analysis/analysis-api/testData/imports/importAliases/propertyAlias.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// TYPE_ALIAS: as bar
1+
// TYPE_ALIAS: bar
22
import Foo.foo as bar
33

44
object Foo {

analysis/kt-references/src/org/jetbrains/kotlin/idea/references/KtReference.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,6 @@ abstract class AbstractKtReference<T : KtElement>(element: T) : PsiPolyVariantRe
129129
&& element.parent !is KtCallExpression
130130
&& !element.isInImportDirective()
131131
}
132-
133-
private fun PsiElement.isConstructorOf(unwrappedCandidate: PsiElement) =
134-
when {
135-
// call to Java constructor
136-
this is PsiMethod && isConstructor && containingClass == unwrappedCandidate -> true
137-
// call to Kotlin constructor
138-
this is KtConstructor<*> && getContainingClassOrObject().isEquivalentTo(unwrappedCandidate) -> true
139-
else -> false
140-
}
141132
}
142133

143134
abstract class KtSimpleReference<T : KtReferenceExpression>(expression: T) : AbstractKtReference<T>(expression)

0 commit comments

Comments
 (0)