KTIJ-26057 [AA] Ignore implicit receivers scope when dealing with types in reference shortener
Implicit receivers generally do not affect the resolution of types. However, they generate scopes which might contain undesirable classifiers, which can confuse reference shortener. Dropping all the implicit receivers when dealing with type references allows completely avoid such undesirable scopes instead of filtering them by `instanceof` checks. Also, temporary move `hasTypeParameterFromParent` check higher to the `findClassifierElementsToShorten`, because ATM we don't know how to properly decide whether to shorten the fully-qualified inner types with implicit parameters or not (see KTIJ-26072). ^KTIJ-26057 Fixed
This commit is contained in:
+21
-26
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression
|
||||
import org.jetbrains.kotlin.fir.java.scopes.JavaClassMembersEnhancementScope
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
@@ -320,15 +319,21 @@ private class FirShorteningContext(val analysisSession: KtFirAnalysisSession) {
|
||||
fun findScopesAtPosition(
|
||||
position: KtElement,
|
||||
newImports: Sequence<FqName>,
|
||||
towerContextProvider: FirTowerContextProvider
|
||||
towerContextProvider: FirTowerContextProvider,
|
||||
withImplicitReceivers: Boolean = true,
|
||||
): List<FirScope>? {
|
||||
val towerDataContext = towerContextProvider.getClosestAvailableParentContext(position) ?: return null
|
||||
val result = buildList {
|
||||
addAll(towerDataContext.nonLocalTowerDataElements.flatMap {
|
||||
val nonLocalScopes = towerDataContext.nonLocalTowerDataElements
|
||||
.asSequence()
|
||||
.filter { withImplicitReceivers || it.implicitReceiver == null }
|
||||
.flatMap {
|
||||
// We must use `it.getAvailableScopes()` instead of `it.scope` to check scopes of companion objects
|
||||
// and context receivers as well.
|
||||
it.getAvailableScopes()
|
||||
})
|
||||
}
|
||||
|
||||
val result = buildList {
|
||||
addAll(nonLocalScopes)
|
||||
addIfNotNull(createFakeImportingScope(newImports))
|
||||
addAll(towerDataContext.localScopes)
|
||||
}
|
||||
@@ -552,8 +557,13 @@ private class ElementsToShortenCollector(
|
||||
wholeClassQualifier: ClassId,
|
||||
wholeQualifierElement: KtElement,
|
||||
): ElementToShorten? {
|
||||
val positionScopes: List<FirScope> =
|
||||
shorteningContext.findScopesAtPosition(wholeQualifierElement, getNamesToImport(), towerContextProvider) ?: return null
|
||||
val positionScopes = shorteningContext.findScopesAtPosition(
|
||||
wholeQualifierElement,
|
||||
getNamesToImport(),
|
||||
towerContextProvider,
|
||||
withImplicitReceivers = false,
|
||||
) ?: return null
|
||||
|
||||
val allClassIds = wholeClassQualifier.outerClassesWithSelf
|
||||
val allQualifiers = wholeQualifierElement.qualifiedElementsWithSelf
|
||||
return findClassifierElementsToShorten(
|
||||
@@ -731,26 +741,8 @@ private class ElementsToShortenCollector(
|
||||
classId: ClassId,
|
||||
element: KtElement,
|
||||
classSymbol: FirClassLikeSymbol<*>,
|
||||
positionScopes: List<FirScope>,
|
||||
scopes: List<FirScope>,
|
||||
): Boolean {
|
||||
// If its parent has a type parameter, we cannot shorten it because it will lose its type parameter.
|
||||
if (classSymbol.hasTypeParameterFromParent()) return false
|
||||
|
||||
/**
|
||||
* Class use-site member scopes may contain classifiers which are not actually available without explicit import.
|
||||
* And if the class is declared in Java, it can be represented with JavaClassMembersEnhancementScope.
|
||||
*/
|
||||
val scopes = positionScopes.filter {
|
||||
when (it) {
|
||||
// KTIJ-24684, KTIJ-24662
|
||||
is FirClassUseSiteMemberScope -> false
|
||||
// KTIJ-26785
|
||||
is JavaClassMembersEnhancementScope -> false
|
||||
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
val name = classId.shortClassName
|
||||
val availableClassifiers = shorteningContext.findClassifiersInScopesByName(scopes, name)
|
||||
val matchingAvailableSymbol = availableClassifiers.firstOrNull { it.availableSymbol.symbol.classIdIfExists == classId }
|
||||
@@ -788,6 +780,9 @@ private class ElementsToShortenCollector(
|
||||
val option = classShortenOption(classSymbol)
|
||||
if (option == ShortenOption.DO_NOT_SHORTEN) continue
|
||||
|
||||
// If its parent has a type parameter, we do not shorten it ATM because it will lose its type parameter. See KTIJ-26072
|
||||
if (classSymbol.hasTypeParameterFromParent()) continue
|
||||
|
||||
if (shortenClassifierIfAlreadyImported(classId, element, classSymbol, positionScopes)) {
|
||||
return createElementToShorten(element, null, false)
|
||||
}
|
||||
|
||||
+12
@@ -643,6 +643,18 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/nestedClassFromSupertypes6_java.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("TypeWithGenericsAsExtensionReceiverType_innerType.kt")
|
||||
public void testTypeWithGenericsAsExtensionReceiverType_innerType() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_innerType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("TypeWithGenericsAsExtensionReceiverType_nestedType.kt")
|
||||
public void testTypeWithGenericsAsExtensionReceiverType_nestedType() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_nestedType.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classHeaderPositions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+12
@@ -643,6 +643,18 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/nestedClassFromSupertypes6_java.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("TypeWithGenericsAsExtensionReceiverType_innerType.kt")
|
||||
public void testTypeWithGenericsAsExtensionReceiverType_innerType() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_innerType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("TypeWithGenericsAsExtensionReceiverType_nestedType.kt")
|
||||
public void testTypeWithGenericsAsExtensionReceiverType_nestedType() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_nestedType.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/classHeaderPositions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class Outer<T> {
|
||||
inner class Inner
|
||||
}
|
||||
|
||||
fun <T> Outer<T>.test(p: <expr>Outer<T>.Inner</expr>) {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
Before shortening: Outer<T>.Inner
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
with SHORTEN_AND_IMPORT:
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class Outer<T> {
|
||||
class Nested
|
||||
}
|
||||
|
||||
fun <T> Outer<T>.test(p: <expr>Outer.Nested</expr>) {}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
Before shortening: Outer.Nested
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
with SHORTEN_AND_IMPORT:
|
||||
[type] Outer.Nested
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
[type] Outer.Nested
|
||||
Reference in New Issue
Block a user