Skip to content

Commit 4e98394

Browse files
committed
Fix Sample reference to resolve cross-module packages correctly
Now @sample links to FqName in IDE will be resolved correctly Cause now we resolve packages over all modules in project #KT-14710 fixed
1 parent 688802d commit 4e98394

File tree

10 files changed

+114
-9
lines changed

10 files changed

+114
-9
lines changed

idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ModuleDependencyMapper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ fun createModuleResolverProvider(
114114
)
115115
}
116116

117-
private fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
117+
fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
118118
val ideaModules = ModuleManager.getInstance(project).modules.toList()
119119
val modulesSourcesInfos = ideaModules.flatMap { listOf(it.productionSourceInfo(), it.testSourceInfo()) }
120120

idea/src/org/jetbrains/kotlin/idea/kdoc/IdeSampleResolutionService.kt renamed to idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/IdeSampleResolutionService.kt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ package org.jetbrains.kotlin.idea.kdoc
1919
import com.intellij.openapi.project.Project
2020
import com.intellij.psi.search.GlobalSearchScope
2121
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
22+
import org.jetbrains.kotlin.idea.caches.resolve.collectAllModuleInfosFromIdeaModel
23+
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
2224
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
2325
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
26+
import org.jetbrains.kotlin.idea.stubindex.KotlinClassShortNameIndex
2427
import org.jetbrains.kotlin.idea.stubindex.KotlinFunctionShortNameIndex
2528
import org.jetbrains.kotlin.name.FqName
2629
import org.jetbrains.kotlin.resolve.BindingContext
@@ -29,16 +32,29 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
2932
class IdeSampleResolutionService(val project: Project) : SampleResolutionService {
3033

3134
override fun resolveSample(context: BindingContext, fromDescriptor: DeclarationDescriptor, resolutionFacade: ResolutionFacade, qualifiedName: List<String>): Collection<DeclarationDescriptor> {
35+
3236
val allScope = GlobalSearchScope.projectScope(project)
37+
3338
val shortName = qualifiedName.lastOrNull() ?: return emptyList()
34-
val functions = KotlinFunctionShortNameIndex.getInstance().get(shortName, project, allScope)
39+
3540
val targetFqName = FqName.fromSegments(qualifiedName)
3641

42+
val functions = KotlinFunctionShortNameIndex.getInstance().get(shortName, project, allScope).asSequence()
43+
val classes = KotlinClassShortNameIndex.getInstance().get(shortName, project, allScope).asSequence()
3744

38-
val descriptors = functions.asSequence()
45+
val descriptors = (functions + classes)
3946
.filter { it.fqName == targetFqName }
4047
.map { it.resolveToDescriptor(BodyResolveMode.PARTIAL) } // TODO Filter out not visible due dependencies config descriptors
4148
.toList()
42-
return descriptors
49+
if(descriptors.isNotEmpty())
50+
return descriptors
51+
52+
val packageDescriptors = collectAllModuleInfosFromIdeaModel(project)
53+
.asSequence()
54+
.map { resolutionFacade.findModuleDescriptor(it)?.getPackage(targetFqName) }
55+
.filterNotNull()
56+
.filterNot { it.isEmpty() }
57+
58+
return packageDescriptors.toList()
4359
}
4460
}

idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KDocCompletionContributor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class KDocNameCompletionSession(
148148
val qualifiedLink = kDocLink.getLinkText().split('.').dropLast(1)
149149
val nameFilter = descriptorNameFilter.toNameFilter()
150150
if (qualifiedLink.isNotEmpty()) {
151-
val parentDescriptors = resolveKDocLink(bindingContext, resolutionFacade, declarationDescriptor, null, qualifiedLink)
151+
val parentDescriptors = resolveKDocLink(bindingContext, resolutionFacade, declarationDescriptor, kDocLink.getTagIfSubject(), qualifiedLink)
152152
val childDescriptorsOfPartialLink = parentDescriptors.asSequence().flatMap {
153153
val scope = getKDocLinkResolutionScope(resolutionFacade, it)
154154
collectDescriptorsFromScope(scope, nameFilter, false)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @sample samples.SampleGroup.mySample
3+
* @sample samples.megasamples.MegaSamplesGroup.megaSample
4+
* @sample samples.notindir.NotInDirSamples.sssample
5+
* @sample smaplez.a.b.c.Samplez.sssample
6+
*/
7+
fun some<caret>() {
8+
9+
}
10+
11+
12+
//INFO: <pre><b>public</b> <b>fun</b> some(): Unit <i>defined in</i> root package</pre><br/>
13+
//INFO: <dl><dt><b>Samples:</b></dt><dd><a href="psi_element://samples.SampleGroup.mySample"><code>samples.SampleGroup.mySample</code></a><pre><code>
14+
//INFO: println("Hello, world")
15+
//INFO: </code></pre></dd><dd><a href="psi_element://samples.megasamples.MegaSamplesGroup.megaSample"><code>samples.megasamples.MegaSamplesGroup.megaSample</code></a><pre><code>
16+
//INFO: println("...---...")
17+
//INFO: </code></pre></dd><dd><a href="psi_element://samples.notindir.NotInDirSamples.sssample"><code>samples.notindir.NotInDirSamples.sssample</code></a><pre><code>
18+
//INFO: println("location is samplesTest/")
19+
//INFO: </code></pre></dd><dd><a href="psi_element://smaplez.a.b.c.Samplez.sssample"><code>smaplez.a.b.c.Samplez.sssample</code></a><pre><code>// Unresolved</code></pre></dd></dl>

idea/testData/kdoc/multiModuleSamples/fqName/samples/EMPTY

Whitespace-only changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package samples.notindir
2+
3+
object NotInDirSamples {
4+
fun sssample() {
5+
println("location is samplesTest/")
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package samples.megasamples
2+
3+
object MegaSamplesGroup {
4+
fun megaSample() {
5+
println("...---...")
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package samples
2+
3+
object SampleGroup {
4+
fun mySample() {
5+
println("Hello, world")
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package samplez.a.b.c
2+
3+
object Samplez {
4+
fun sssample() {
5+
println("samplez")
6+
}
7+
}

idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocSampleTest.kt

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@ import com.intellij.openapi.util.io.FileUtil
2121
import com.intellij.openapi.util.text.StringUtil
2222
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
2323
import com.intellij.rt.execution.junit.FileComparisonFailure
24+
import org.jetbrains.kotlin.idea.caches.resolve.analyze
25+
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
2426
import org.jetbrains.kotlin.idea.editor.quickDoc.AbstractQuickDocProviderTest.wrapToFileComparisonFailure
2527
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest
28+
import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
29+
import org.jetbrains.kotlin.psi.KtElement
30+
import org.jetbrains.kotlin.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR
2631
import org.jetbrains.kotlin.test.InTextDirectivesUtils
2732
import org.jetbrains.kotlin.test.KotlinTestUtils
2833
import java.io.File
@@ -44,10 +49,47 @@ class KDocSampleTest : AbstractMultiModuleTest() {
4449

4550
samples.addDependency(code)
4651

47-
doTest("simple/code/usage.kt")
52+
doInfoTest("simple/code/usage.kt")
4853
}
4954

50-
fun doTest(path: String) {
55+
fun testFqName() {
56+
57+
val code = module("code")
58+
val samples = module("samples", hasTestRoot = true)
59+
60+
samples.addDependency(code)
61+
62+
doInfoTest("fqName/code/usage.kt")
63+
doResolveTest("fqName/code/usage.kt", "samples")
64+
doResolveTest("fqName/code/usage.kt", "samples.SampleGroup")
65+
doResolveTest("fqName/code/usage.kt", "samples.megasamples")
66+
doResolveTest("fqName/code/usage.kt", "samples.megasamples.MegaSamplesGroup")
67+
doResolveTest("fqName/code/usage.kt", "samples.notindir")
68+
doResolveTest("fqName/code/usage.kt", "samples.notindir.NotInDirSamples")
69+
doResolveTest("fqName/code/usage.kt", "samplez")
70+
doResolveTest("fqName/code/usage.kt", "samplez.a")
71+
doResolveTest("fqName/code/usage.kt", "samplez.a.b")
72+
doResolveTest("fqName/code/usage.kt", "samplez.a.b.c")
73+
doResolveTest("fqName/code/usage.kt", "samplez.a.b.c.Samplez")
74+
}
75+
76+
fun doResolveTest(path: String, link: String) {
77+
78+
configureByFile(path)
79+
val documentationManager = DocumentationManager.getInstance(myProject)
80+
val targetElement = documentationManager.findTargetElement(myEditor, file)
81+
82+
targetElement as KtElement
83+
84+
val bindingContext = targetElement.analyze()
85+
val descriptor = bindingContext[DECLARATION_TO_DESCRIPTOR, targetElement]!!
86+
val kdoc = descriptor.findKDoc()!! as KDocSection
87+
val resolutionFacade = targetElement.getResolutionFacade()
88+
assertNotEmpty(resolveKDocLink(bindingContext, resolutionFacade, descriptor, kdoc.findTagByName("sample")!!, link.split(".")))
89+
90+
}
91+
92+
fun doInfoTest(path: String) {
5193
val testDataFile = File(testPath, path)
5294
configureByFile(path)
5395
val documentationManager = DocumentationManager.getInstance(myProject)
@@ -77,11 +119,11 @@ class KDocSampleTest : AbstractMultiModuleTest() {
77119

78120
if (expectedInfo.endsWith("...\n")) {
79121
if (!info!!.startsWith(expectedInfo.removeSuffix("...\n"))) {
80-
wrapToFileComparisonFailure(info, testDataPath, textData)
122+
wrapToFileComparisonFailure(info, testDataFile.absolutePath, textData)
81123
}
82124
}
83125
else if (expectedInfo != info) {
84-
wrapToFileComparisonFailure(info, path, textData)
126+
wrapToFileComparisonFailure(info!!, testDataFile.absolutePath, textData)
85127
}
86128
}
87129
}

0 commit comments

Comments
 (0)