From 3ec032212cc300dadac3d36ee8f39a33b2c4d966 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Fri, 28 Oct 2022 10:35:23 +0200 Subject: [PATCH] [Analysis API] Ignore FirClassUseSiteMemberScope scopes in KtFirReferenceShortener Those scopes always contain all nested classifiers, while only some of them are available without explicit import. There are other, more reliable scopes (like FirNestedClassifierScopeWithSubstitution) which are stricter about which classifiers they recognise as valid ^KTIJ-24684 Fixed ^KTIJ-24662 Fixed --- .../fir/components/KtFirReferenceShortener.kt | 12 +++++-- ...ModuleReferenceShortenerTestGenerated.java | 36 +++++++++++++++++++ ...ModuleReferenceShortenerTestGenerated.java | 36 +++++++++++++++++++ .../nestedClassFromSupertypes.kt | 9 +++++ .../nestedClassFromSupertypes.txt | 9 +++++ .../nestedClassFromSupertypes2.kt | 10 ++++++ .../nestedClassFromSupertypes2.txt | 11 ++++++ .../nestedClassFromSupertypes3.kt | 8 +++++ .../nestedClassFromSupertypes3.txt | 11 ++++++ .../nestedClassFromSupertypes4.kt | 6 ++++ .../nestedClassFromSupertypes4.txt | 11 ++++++ .../nestedClassFromSupertypes5.kt | 8 +++++ .../nestedClassFromSupertypes5.txt | 9 +++++ .../nestedClassFromSupertypes6.kt | 8 +++++ .../nestedClassFromSupertypes6.txt | 9 +++++ 15 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.kt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes.txt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.kt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes2.txt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.kt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes3.txt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.kt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes4.txt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.kt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes5.txt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.kt create mode 100644 analysis/analysis-api/testData/components/referenceShortener/referenceShortener/nestedClassFromSupertypes6.txt 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()