[K2] Include Type Aliases in targets when resolving constructors
Refactoring and UX relies on type aliases being included in the result
when resolving constructor invocations.
This commit introduces a "fix-up" that checks whether a constructor
invocation _also_ matches a type declaration. If that declaration is
an alias, we inject that symbol into the resolution result.
diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt
index 2261fcf..3803fbd 100644
--- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt
+++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirSimpleNameReference.kt
@@ -7,11 +7,16 @@
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
+import org.jetbrains.kotlin.analysis.api.components.buildClassType
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
+import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirConstructorSymbol
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSyntheticJavaPropertySymbol
+import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirTypeAliasSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
+import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
+import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.*
internal class KtFirSimpleNameReference(
@@ -27,6 +32,10 @@
return ktConstructorCalleeExpression.parent is KtAnnotationEntry
}
+ /**
+ * This fix-up needed to resolve annotation call into annotation
+ * constructor (but not into the annotation type).
+ */
private fun KtAnalysisSession.fixUpAnnotationCallResolveToCtor(resultsToFix: Collection<KtSymbol>): Collection<KtSymbol> {
if (resultsToFix.isEmpty() || !isAnnotationCall) return resultsToFix
@@ -37,11 +46,37 @@
}
}
+ /**
+ * This pass introduces additional symbols into the resolution result for
+ * constructor invocations that resolve via a type-alias. The type-alias
+ * needs to be included in the resolution result in order to support
+ * refactorings that rely on resolution (e.g. to find rename targets).
+ *
+ * We take the _name_ of the constructor, and attempt to resolve it as a
+ * type. If the declaration of that type is an alias, we include it in the
+ * result.
+ */
+ private fun KtAnalysisSession.includeTypeAliasesForConstructorCalls(resultsToFix: Collection<KtSymbol>): Collection<KtSymbol> {
+ return resultsToFix.flatMap { targetSymbol ->
+ if (targetSymbol !is KtFirConstructorSymbol) return@flatMap listOf(targetSymbol)
+ val name = expression.getReferencedName()
+ val fakeType = ClassId.fromString(name)
+ val classType = buildClassType(fakeType)
+ if (classType !is KtNonErrorClassType) return@flatMap listOf(targetSymbol)
+ if (classType.classSymbol is KtFirTypeAliasSymbol) {
+ return@flatMap listOf(targetSymbol, classType.classSymbol)
+ } else {
+ return@flatMap listOf(targetSymbol)
+ }
+ }
+ }
+
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
check(this is KtFirAnalysisSession)
- val results = FirReferenceResolveHelper.resolveSimpleNameReference(this@KtFirSimpleNameReference, this)
- //This fix-up needed to resolve annotation call into annotation constructor (but not into the annotation type)
- return fixUpAnnotationCallResolveToCtor(results)
+ var results = FirReferenceResolveHelper.resolveSimpleNameReference(this@KtFirSimpleNameReference, this)
+ results = fixUpAnnotationCallResolveToCtor(results)
+ results = includeTypeAliasesForConstructorCalls(results)
+ return results
}
override fun getResolvedToPsi(analysisSession: KtAnalysisSession): Collection<PsiElement> = with(analysisSession) {
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java
index 2eeb28f..48388e6 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java
@@ -53,6 +53,18 @@
}
@Test
+ @TestMetadata("chainOfTypeAliasesBottom.kt")
+ public void testChainOfTypeAliasesBottom() throws Exception {
+ runTest("analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.kt");
+ }
+
+ @Test
+ @TestMetadata("chainOfTypeAliasesTop.kt")
+ public void testChainOfTypeAliasesTop() throws Exception {
+ runTest("analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.kt");
+ }
+
+ @Test
@TestMetadata("constructorViaTypeAlias.kt")
public void testConstructorViaTypeAlias() throws Exception {
runTest("analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.kt");
diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/symbols/AbstractSymbolByReferenceTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/symbols/AbstractSymbolByReferenceTest.kt
index 5d7c9eb..3c507db 100644
--- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/symbols/AbstractSymbolByReferenceTest.kt
+++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/symbols/AbstractSymbolByReferenceTest.kt
@@ -16,7 +16,7 @@
override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): SymbolsData {
val referenceExpression = testServices.expressionMarkerProvider.getElementOfTypeAtCaret<KtNameReferenceExpression>(ktFile)
return SymbolsData(
- listOfNotNull(referenceExpression.mainReference.resolveToSymbol())
+ referenceExpression.mainReference.resolveToSymbols().toList()
)
}
}
\ No newline at end of file
diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java
index 55e0485..624ecb0 100644
--- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java
+++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSymbolByReferenceTestGenerated.java
@@ -53,6 +53,18 @@
}
@Test
+ @TestMetadata("chainOfTypeAliasesBottom.kt")
+ public void testChainOfTypeAliasesBottom() throws Exception {
+ runTest("analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.kt");
+ }
+
+ @Test
+ @TestMetadata("chainOfTypeAliasesTop.kt")
+ public void testChainOfTypeAliasesTop() throws Exception {
+ runTest("analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.kt");
+ }
+
+ @Test
@TestMetadata("constructorViaTypeAlias.kt")
public void testConstructorViaTypeAlias() throws Exception {
runTest("analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.kt");
diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.kt b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.kt
new file mode 100644
index 0000000..bb83a68
--- /dev/null
+++ b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.kt
@@ -0,0 +1,10 @@
+// DO_NOT_CHECK_SYMBOL_RESTORE
+
+class A
+typealias B = A
+typealias C = B
+typealias D = C
+
+fun x() {
+ val a = <caret>D()
+}
diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.pretty.txt
new file mode 100644
index 0000000..ea227f7
--- /dev/null
+++ b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.pretty.txt
@@ -0,0 +1,3 @@
+constructor()
+
+typealias D = C
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.txt b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.txt
new file mode 100644
index 0000000..958e849
--- /dev/null
+++ b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesBottom.txt
@@ -0,0 +1,29 @@
+KtConstructorSymbol:
+ annotationsList: []
+ callableIdIfNonLocal: null
+ containingClassIdIfNonLocal: A
+ contextReceivers: []
+ hasStableParameterNames: true
+ isExtension: false
+ isPrimary: true
+ origin: SOURCE_MEMBER_GENERATED
+ receiverType: null
+ returnType: A
+ symbolKind: CLASS_MEMBER
+ typeParameters: []
+ valueParameters: []
+ visibility: Public
+ getContainingModule: KtSourceModule "Sources of main"
+ deprecationStatus: null
+
+KtTypeAliasSymbol:
+ annotationsList: []
+ classIdIfNonLocal: D
+ expandedType: C
+ name: D
+ origin: SOURCE
+ symbolKind: TOP_LEVEL
+ typeParameters: []
+ visibility: Public
+ getContainingModule: KtSourceModule "Sources of main"
+ deprecationStatus: null
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.kt b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.kt
new file mode 100644
index 0000000..d7214e0
--- /dev/null
+++ b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.kt
@@ -0,0 +1,10 @@
+// DO_NOT_CHECK_SYMBOL_RESTORE
+
+class A
+typealias B = A
+typealias C = B
+typealias D = C
+
+fun x() {
+ val a = <caret>B()
+}
diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.pretty.txt
new file mode 100644
index 0000000..81682ee
--- /dev/null
+++ b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.pretty.txt
@@ -0,0 +1,3 @@
+constructor()
+
+typealias B = A
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.txt b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.txt
new file mode 100644
index 0000000..29f165b
--- /dev/null
+++ b/analysis/analysis-api/testData/symbols/symbolByReference/chainOfTypeAliasesTop.txt
@@ -0,0 +1,29 @@
+KtConstructorSymbol:
+ annotationsList: []
+ callableIdIfNonLocal: null
+ containingClassIdIfNonLocal: A
+ contextReceivers: []
+ hasStableParameterNames: true
+ isExtension: false
+ isPrimary: true
+ origin: SOURCE_MEMBER_GENERATED
+ receiverType: null
+ returnType: A
+ symbolKind: CLASS_MEMBER
+ typeParameters: []
+ valueParameters: []
+ visibility: Public
+ getContainingModule: KtSourceModule "Sources of main"
+ deprecationStatus: null
+
+KtTypeAliasSymbol:
+ annotationsList: []
+ classIdIfNonLocal: B
+ expandedType: A
+ name: B
+ origin: SOURCE
+ symbolKind: TOP_LEVEL
+ typeParameters: []
+ visibility: Public
+ getContainingModule: KtSourceModule "Sources of main"
+ deprecationStatus: null
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.pretty.txt
index 20cbaa6..ee5d07f 100644
--- a/analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.pretty.txt
+++ b/analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.pretty.txt
@@ -1 +1,4 @@
constructor(c: kotlin.collections.(Mutable)Collection<out (E!!..E?)>!)
+
+@kotlin.SinceKotlin(version = "1.1")
+typealias ArrayList<E> = java.util.ArrayList<E>
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.txt b/analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.txt
index 146b0c0..0851407 100644
--- a/analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.txt
+++ b/analysis/analysis-api/testData/symbols/symbolByReference/constructorViaTypeAlias.txt
@@ -18,4 +18,21 @@
]
visibility: Public
getContainingModule: KtSdkModule "SDK jdk"
+ deprecationStatus: null
+
+KtTypeAliasSymbol:
+ annotationsList: [
+ kotlin/SinceKotlin(version = "1.1")
+ psi: null
+ ]
+ classIdIfNonLocal: kotlin/collections/ArrayList
+ expandedType: java/util/ArrayList<E>
+ name: ArrayList
+ origin: LIBRARY
+ symbolKind: TOP_LEVEL
+ typeParameters: [
+ KtTypeParameterSymbol(E)
+ ]
+ visibility: Public
+ getContainingModule: KtLibraryModule "Library kotlin-stdlib"
deprecationStatus: null
\ No newline at end of file