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 d8266e72870..ef3931c8933 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 @@ -36,7 +36,6 @@ 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.expressions.impl.FirNoReceiverExpression -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference @@ -601,8 +600,15 @@ private class ElementsToShortenCollector( // 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. + * + * See KTIJ-24684 and KTIJ-24662 for examples. + */ + val scopes = positionScopes.filterNot { it is FirClassUseSiteMemberScope } + val name = classId.shortClassName - val availableClassifiers = shorteningContext.findClassifiersInScopesByName(positionScopes, name) + val availableClassifiers = shorteningContext.findClassifiersInScopesByName(scopes, name) val matchingAvailableSymbol = availableClassifiers.firstOrNull { it.availableSymbol.symbol == classId } val scopeForClass = matchingAvailableSymbol?.scope ?: return false @@ -618,7 +624,7 @@ private class ElementsToShortenCollector( * my.component.foo::class.java // If we drop `my.component`, it will reference `B` instead of `A` * } */ - if (shorteningContext.findPropertiesInScopes(positionScopes, name).isNotEmpty()) { + if (shorteningContext.findPropertiesInScopes(scopes, name).isNotEmpty()) { val firForElement = element.getOrBuildFir(firResolveSession) as? FirQualifiedAccessExpression val typeArguments = firForElement?.typeArguments ?: emptyList() val qualifiedAccessCandidates = findCandidatesForPropertyAccess(classSymbol.annotations, typeArguments, name, element) 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 770525932d9..780b1df440c 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 @@ -196,6 +196,42 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClass3.kt"); } + @Test + @TestMetadata("nestedClassFromSupertypes.kt") + public void testNestedClassFromSupertypes() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes2.kt") + public void testNestedClassFromSupertypes2() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes3.kt") + public void testNestedClassFromSupertypes3() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes4.kt") + public void testNestedClassFromSupertypes4() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes5.kt") + public void testNestedClassFromSupertypes5() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes6.kt") + public void testNestedClassFromSupertypes6() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.kt"); + } + @Test @TestMetadata("parameterTypeTopLevelTypeLoses.kt") public void testParameterTypeTopLevelTypeLoses() throws Exception { 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 a74cddec90e..21c5f6d45e0 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 @@ -196,6 +196,42 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClass3.kt"); } + @Test + @TestMetadata("nestedClassFromSupertypes.kt") + public void testNestedClassFromSupertypes() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes2.kt") + public void testNestedClassFromSupertypes2() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes3.kt") + public void testNestedClassFromSupertypes3() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes4.kt") + public void testNestedClassFromSupertypes4() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes5.kt") + public void testNestedClassFromSupertypes5() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.kt"); + } + + @Test + @TestMetadata("nestedClassFromSupertypes6.kt") + public void testNestedClassFromSupertypes6() throws Exception { + runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.kt"); + } + @Test @TestMetadata("parameterTypeTopLevelTypeLoses.kt") public void testParameterTypeTopLevelTypeLoses() throws Exception { diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.kt new file mode 100644 index 00000000000..487561528ae --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.kt @@ -0,0 +1,9 @@ +// FILE: main.kt + +interface MyInterface { + class Nested +} + +class Foo : MyInterface { + val prop: MyInterface.Nested = MyInterface.Nested() +} diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.txt new file mode 100644 index 00000000000..75e85c4b526 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.txt @@ -0,0 +1,9 @@ +Before shortening: val prop: MyInterface.Nested = MyInterface.Nested() +with DO_NOT_SHORTEN: +with SHORTEN_IF_ALREADY_IMPORTED: +with SHORTEN_AND_IMPORT: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() +with SHORTEN_AND_STAR_IMPORT: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.kt new file mode 100644 index 00000000000..f0cd04008bd --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.kt @@ -0,0 +1,10 @@ +// FILE: main.kt +import MyInterface.Nested + +interface MyInterface { + class Nested +} + +class Foo : MyInterface { + val prop: MyInterface.Nested = MyInterface.Nested() +} diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.txt new file mode 100644 index 00000000000..d852fea443e --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.txt @@ -0,0 +1,11 @@ +Before shortening: val prop: MyInterface.Nested = MyInterface.Nested() +with DO_NOT_SHORTEN: +with SHORTEN_IF_ALREADY_IMPORTED: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() +with SHORTEN_AND_IMPORT: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() +with SHORTEN_AND_STAR_IMPORT: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.kt new file mode 100644 index 00000000000..293e78dfa83 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.kt @@ -0,0 +1,8 @@ +// FILE: main.kt +open class MyBaseClass { + class Nested +} + +class Foo : MyBaseClass() { + val prop: MyBaseClass.Nested = MyBaseClass.Nested() +} diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.txt new file mode 100644 index 00000000000..6c1430ef188 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.txt @@ -0,0 +1,11 @@ +Before shortening: val prop: MyBaseClass.Nested = MyBaseClass.Nested() +with DO_NOT_SHORTEN: +with SHORTEN_IF_ALREADY_IMPORTED: +[type] MyBaseClass.Nested +[qualifier] MyBaseClass.Nested() +with SHORTEN_AND_IMPORT: +[type] MyBaseClass.Nested +[qualifier] MyBaseClass.Nested() +with SHORTEN_AND_STAR_IMPORT: +[type] MyBaseClass.Nested +[qualifier] MyBaseClass.Nested() diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.kt new file mode 100644 index 00000000000..6a88bb4f63a --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.kt @@ -0,0 +1,6 @@ +// FILE: main.kt +interface MyInterface { + class Nested + + val prop: MyInterface.Nested get() = MyInterface.Nested() +} diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.txt new file mode 100644 index 00000000000..3d4f1bf538c --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.txt @@ -0,0 +1,11 @@ +Before shortening: val prop: MyInterface.Nested get() = MyInterface.Nested() +with DO_NOT_SHORTEN: +with SHORTEN_IF_ALREADY_IMPORTED: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() +with SHORTEN_AND_IMPORT: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() +with SHORTEN_AND_STAR_IMPORT: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.kt new file mode 100644 index 00000000000..716f60b9ba2 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.kt @@ -0,0 +1,8 @@ +// FILE: main.kt +interface MyInterface { + class Nested +} + +fun MyInterface.foo() { + val prop: MyInterface.Nested = MyInterface.Nested() +} diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.txt new file mode 100644 index 00000000000..75e85c4b526 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.txt @@ -0,0 +1,9 @@ +Before shortening: val prop: MyInterface.Nested = MyInterface.Nested() +with DO_NOT_SHORTEN: +with SHORTEN_IF_ALREADY_IMPORTED: +with SHORTEN_AND_IMPORT: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() +with SHORTEN_AND_STAR_IMPORT: +[type] MyInterface.Nested +[qualifier] MyInterface.Nested() diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.kt new file mode 100644 index 00000000000..cf92cd81506 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.kt @@ -0,0 +1,8 @@ +// FILE: main.kt +open class MyBaseClass { + class Nested +} + +fun MyBaseClass.foo() { + val prop: MyBaseClass.Nested = MyBaseClass.Nested() +} diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.txt new file mode 100644 index 00000000000..6e35eb2a1f4 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.txt @@ -0,0 +1,9 @@ +Before shortening: val prop: MyBaseClass.Nested = MyBaseClass.Nested() +with DO_NOT_SHORTEN: +with SHORTEN_IF_ALREADY_IMPORTED: +with SHORTEN_AND_IMPORT: +[type] MyBaseClass.Nested +[qualifier] MyBaseClass.Nested() +with SHORTEN_AND_STAR_IMPORT: +[type] MyBaseClass.Nested +[qualifier] MyBaseClass.Nested()