diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt index da1d15003e0..b905bb64a7b 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt @@ -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, - towerContextProvider: FirTowerContextProvider + towerContextProvider: FirTowerContextProvider, + withImplicitReceivers: Boolean = true, ): List? { 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 = - 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, + scopes: List, ): 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) } diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java index ea778944908..cd51f691621 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java @@ -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") diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java index ab996f39ded..142e614a7c2 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java @@ -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") diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_innerType.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_innerType.kt new file mode 100644 index 00000000000..68658f7116e --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_innerType.kt @@ -0,0 +1,7 @@ +package test + +class Outer { + inner class Inner +} + +fun Outer.test(p: Outer.Inner) {} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_innerType.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_innerType.txt new file mode 100644 index 00000000000..9a71427afd8 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_innerType.txt @@ -0,0 +1,5 @@ +Before shortening: Outer.Inner +with DO_NOT_SHORTEN: +with SHORTEN_IF_ALREADY_IMPORTED: +with SHORTEN_AND_IMPORT: +with SHORTEN_AND_STAR_IMPORT: diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_nestedType.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_nestedType.kt new file mode 100644 index 00000000000..91d979faf2b --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_nestedType.kt @@ -0,0 +1,7 @@ +package test + +class Outer { + class Nested +} + +fun Outer.test(p: Outer.Nested) {} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_nestedType.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_nestedType.txt new file mode 100644 index 00000000000..cea78ad2998 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClasses/TypeWithGenericsAsExtensionReceiverType_nestedType.txt @@ -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