From d45662c2c346fb3ce7809877954eafea83fb5e07 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Wed, 24 Jan 2024 23:45:10 +0100 Subject: [PATCH] KT-62695 [AA] Better resolve ambiguous receiver types in `KDocReferenceResolver` When encountering multiple available same named types, resolve all of them together with corresponding extensions. This aligns well with the current resolve behavior of classes with the same name (see `SameNameClassesFromStarImports.kt`) Also, add extra test for resolving the ambiguous type without the extension function. The behavior is the same - resolve to the both classes. --- ...ceModuleReferenceResolveTestGenerated.java | 18 ++++++++ .../fir/references/KDocReferenceResolver.kt | 13 +++--- ...ceModuleReferenceResolveTestGenerated.java | 18 ++++++++ ...ceModuleReferenceResolveTestGenerated.java | 18 ++++++++ ...ceModuleReferenceResolveTestGenerated.java | 18 ++++++++ ...ceModuleReferenceResolveTestGenerated.java | 18 ++++++++ .../receiverTypesWithSameName_nestedScopes.kt | 35 +++++++++++++++ ...receiverTypesWithSameName_nestedScopes.txt | 26 +++++++++++ .../receiverTypesWithSameName_starImports.kt | 44 +++++++++++++++++++ .../receiverTypesWithSameName_starImports.txt | 32 ++++++++++++++ .../imports/SameNameClassesFromStarImports.kt | 24 ++++++++++ .../SameNameClassesFromStarImports.txt | 9 ++++ 12 files changed, 266 insertions(+), 7 deletions(-) create mode 100644 analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.txt create mode 100644 analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.txt create mode 100644 analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt create mode 100644 analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.txt diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/references/Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/references/Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated.java index a138d6df429..7995d824e62 100644 --- a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/references/Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/references/Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated.java @@ -1486,6 +1486,18 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/qualifiers.kt"); } + @Test + @TestMetadata("receiverTypesWithSameName_nestedScopes.kt") + public void testReceiverTypesWithSameName_nestedScopes() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt"); + } + + @Test + @TestMetadata("receiverTypesWithSameName_starImports.kt") + public void testReceiverTypesWithSameName_starImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt"); + } + @Test @TestMetadata("topLevelFunction.kt") public void testTopLevelFunction() throws Exception { @@ -1554,6 +1566,12 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/kDoc/imports"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("SameNameClassesFromStarImports.kt") + public void testSameNameClassesFromStarImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt"); + } + @Test @TestMetadata("TypeAliasedImport.kt") public void testTypeAliasedImport() throws Exception { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KDocReferenceResolver.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KDocReferenceResolver.kt index 8edeb0f8c02..7e7ba704f65 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KDocReferenceResolver.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/KDocReferenceResolver.kt @@ -60,7 +60,7 @@ internal object KDocReferenceResolver { context(KtAnalysisSession) internal fun resolveKdocFqName(selectedFqName: FqName, fullFqName: FqName, contextElement: KtElement): Collection { val fullSymbolsResolved = resolveKdocFqName(fullFqName, contextElement) - if (selectedFqName == fullFqName) return fullSymbolsResolved.map { it.symbol } + if (selectedFqName == fullFqName) return fullSymbolsResolved.mapTo(mutableSetOf()) { it.symbol } if (fullSymbolsResolved.isEmpty()) { val parent = fullFqName.parent() return resolveKdocFqName(selectedFqName = selectedFqName, fullFqName = parent, contextElement = contextElement) @@ -290,13 +290,12 @@ internal object KDocReferenceResolver { val possibleReceivers = getReceiverTypeCandidates(receiverTypeName, contextElement) - // we abandon resolve if there are multiple different classifiers in scope - val receiverClassSymbol = possibleReceivers.singleOrNull() ?: return emptyList() - val receiverType = buildClassType(receiverClassSymbol) + return possibleReceivers.flatMap { receiverClassSymbol -> + val receiverType = buildClassType(receiverClassSymbol) + val applicableExtensions = possibleExtensions.filter { it.canBeReferencedAsExtensionOn(receiverType) } - return possibleExtensions - .filter { it.canBeReferencedAsExtensionOn(receiverType) } - .map { it.toResolveResult(receiverClassReference = receiverClassSymbol) } + applicableExtensions.map { it.toResolveResult(receiverClassReference = receiverClassSymbol) } + } } context(KtAnalysisSession) diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated.java index 222d2dd339b..2f09667189c 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated.java @@ -1486,6 +1486,18 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/qualifiers.kt"); } + @Test + @TestMetadata("receiverTypesWithSameName_nestedScopes.kt") + public void testReceiverTypesWithSameName_nestedScopes() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt"); + } + + @Test + @TestMetadata("receiverTypesWithSameName_starImports.kt") + public void testReceiverTypesWithSameName_starImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt"); + } + @Test @TestMetadata("topLevelFunction.kt") public void testTopLevelFunction() throws Exception { @@ -1554,6 +1566,12 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/kDoc/imports"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("SameNameClassesFromStarImports.kt") + public void testSameNameClassesFromStarImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt"); + } + @Test @TestMetadata("TypeAliasedImport.kt") public void testTypeAliasedImport() throws Exception { diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerated.java index 5c5a1e72327..fd1ed590e86 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerated.java @@ -1370,6 +1370,18 @@ public class FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerate runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/qualifiers.kt"); } + @Test + @TestMetadata("receiverTypesWithSameName_nestedScopes.kt") + public void testReceiverTypesWithSameName_nestedScopes() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt"); + } + + @Test + @TestMetadata("receiverTypesWithSameName_starImports.kt") + public void testReceiverTypesWithSameName_starImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt"); + } + @Test @TestMetadata("topLevelFunction.kt") public void testTopLevelFunction() throws Exception { @@ -1438,6 +1450,12 @@ public class FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerate KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/kDoc/imports"), Pattern.compile("^([^.]+)\\.kt$"), null, true, "withErrors"); } + @Test + @TestMetadata("SameNameClassesFromStarImports.kt") + public void testSameNameClassesFromStarImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt"); + } + @Test @TestMetadata("TypeAliasedImport.kt") public void testTypeAliasedImport() throws Exception { diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated.java index 559f5d187e6..cf6d5529839 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated.java @@ -1486,6 +1486,18 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/qualifiers.kt"); } + @Test + @TestMetadata("receiverTypesWithSameName_nestedScopes.kt") + public void testReceiverTypesWithSameName_nestedScopes() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt"); + } + + @Test + @TestMetadata("receiverTypesWithSameName_starImports.kt") + public void testReceiverTypesWithSameName_starImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt"); + } + @Test @TestMetadata("topLevelFunction.kt") public void testTopLevelFunction() throws Exception { @@ -1554,6 +1566,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/kDoc/imports"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("SameNameClassesFromStarImports.kt") + public void testSameNameClassesFromStarImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt"); + } + @Test @TestMetadata("TypeAliasedImport.kt") public void testTypeAliasedImport() throws Exception { diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerated.java index 86cbdc06bbe..45e0632a28a 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerated.java @@ -1486,6 +1486,18 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/qualifiers.kt"); } + @Test + @TestMetadata("receiverTypesWithSameName_nestedScopes.kt") + public void testReceiverTypesWithSameName_nestedScopes() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt"); + } + + @Test + @TestMetadata("receiverTypesWithSameName_starImports.kt") + public void testReceiverTypesWithSameName_starImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt"); + } + @Test @TestMetadata("topLevelFunction.kt") public void testTopLevelFunction() throws Exception { @@ -1554,6 +1566,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/kDoc/imports"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("SameNameClassesFromStarImports.kt") + public void testSameNameClassesFromStarImports() throws Exception { + runTest("analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt"); + } + @Test @TestMetadata("TypeAliasedImport.kt") public void testTypeAliasedImport() throws Exception { diff --git a/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt b/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt new file mode 100644 index 00000000000..1e61f539cf4 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.kt @@ -0,0 +1,35 @@ +package test + +fun Any.ext() {} + +class Foo + +class Outer { + class Foo + + /** + * [Foo.ext] + * + * [Outer.Foo.ext] + * [test.Outer.Foo.ext] + * + * [test.Foo.ext] + */ + fun test1() {} + + class Nested { + + class Foo + + /** + * [Foo.ext] + * + * [Nested.Foo.ext] + * [Outer.Nested.Foo.ext] + * [test.Outer.Nested.Foo.ext] + * + * [test.Foo.ext] + */ + fun test2() {} + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.txt b/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.txt new file mode 100644 index 00000000000..08e8d4461bc --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_nestedScopes.txt @@ -0,0 +1,26 @@ + resolved to: +0: (in test.Outer) class Foo + + resolved to: +0: (in test.Outer) class Foo + + resolved to: +0: (in test.Outer) class Foo + + resolved to: +0: (in test) class Foo + + resolved to: +0: (in test.Outer.Nested) class Foo + + resolved to: +0: (in test.Outer.Nested) class Foo + + resolved to: +0: (in test.Outer.Nested) class Foo + + resolved to: +0: (in test.Outer.Nested) class Foo + + resolved to: +0: (in test) class Foo diff --git a/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt b/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt new file mode 100644 index 00000000000..e122567f027 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.kt @@ -0,0 +1,44 @@ +// FILE: main.kt +package test + +import dep2.* +import dep1.* + +fun Any.ext() {} + +/** + * [Foo.ext] + * [Foo.ext] + * + * [Foo.depExtShared] + * [Foo.depExtShared] + * + * [Foo.depExt1] + * [Foo.depExt1] + * + * [Foo.depExt2] + * [Foo.depExt2] + * + * [dep1.Foo.ext] + * [dep2.Foo.ext] + */ +fun test() {} + +// FILE: dep1.kt +package dep1 + +class Foo + +fun Foo.depExtShared() {} + +fun Foo.depExt1() {} + +// FILE: dep2.kt +package dep2 + +class Foo + +fun Foo.depExtShared() {} + +fun Foo.depExt2() {} + diff --git a/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.txt b/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.txt new file mode 100644 index 00000000000..9d870fd7a36 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/kDoc/extensions/receiverTypesWithSameName_starImports.txt @@ -0,0 +1,32 @@ + resolved to: +0: (in test) fun kotlin.Any.ext() + + resolved to: +0: (in dep1) class Foo +1: (in dep2) class Foo + + resolved to: +0: (in dep1) fun dep1.Foo.depExtShared() +1: (in dep2) fun dep2.Foo.depExtShared() + + resolved to: +0: (in dep1) class Foo +1: (in dep2) class Foo + + resolved to: +0: (in dep1) fun dep1.Foo.depExt1() + + resolved to: +0: (in dep1) class Foo + + resolved to: +0: (in dep2) fun dep2.Foo.depExt2() + + resolved to: +0: (in dep2) class Foo + + resolved to: +0: (in dep1) class Foo + + resolved to: +0: (in dep2) class Foo diff --git a/analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt b/analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt new file mode 100644 index 00000000000..b20c9e8b910 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.kt @@ -0,0 +1,24 @@ +// FILE: main.kt +package test + +import dep2.* +import dep1.* + +/** + * [Foo] + * + * [dep1.Foo] + * [dep2.Foo] + */ +fun test() {} + +// FILE: dep1.kt +package dep1 + +class Foo + +// FILE: dep2.kt +package dep2 + +class Foo + diff --git a/analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.txt b/analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.txt new file mode 100644 index 00000000000..db27071b931 --- /dev/null +++ b/analysis/analysis-api/testData/referenceResolve/kDoc/imports/SameNameClassesFromStarImports.txt @@ -0,0 +1,9 @@ + resolved to: +0: (in dep1) class Foo +1: (in dep2) class Foo + + resolved to: +0: (in dep1) class Foo + + resolved to: +0: (in dep2) class Foo