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
This commit is contained in:
+1
-1
@@ -114,7 +114,7 @@ fun createModuleResolverProvider(
|
||||
)
|
||||
}
|
||||
|
||||
private fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
|
||||
fun collectAllModuleInfosFromIdeaModel(project: Project): List<IdeaModuleInfo> {
|
||||
val ideaModules = ModuleManager.getInstance(project).modules.toList()
|
||||
val modulesSourcesInfos = ideaModules.flatMap { listOf(it.productionSourceInfo(), it.testSourceInfo()) }
|
||||
|
||||
|
||||
+19
-3
@@ -19,8 +19,11 @@ package org.jetbrains.kotlin.idea.kdoc
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.collectAllModuleInfosFromIdeaModel
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinClassShortNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFunctionShortNameIndex
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -29,16 +32,29 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
class IdeSampleResolutionService(val project: Project) : SampleResolutionService {
|
||||
|
||||
override fun resolveSample(context: BindingContext, fromDescriptor: DeclarationDescriptor, resolutionFacade: ResolutionFacade, qualifiedName: List<String>): Collection<DeclarationDescriptor> {
|
||||
|
||||
val allScope = GlobalSearchScope.projectScope(project)
|
||||
|
||||
val shortName = qualifiedName.lastOrNull() ?: return emptyList()
|
||||
val functions = KotlinFunctionShortNameIndex.getInstance().get(shortName, project, allScope)
|
||||
|
||||
val targetFqName = FqName.fromSegments(qualifiedName)
|
||||
|
||||
val functions = KotlinFunctionShortNameIndex.getInstance().get(shortName, project, allScope).asSequence()
|
||||
val classes = KotlinClassShortNameIndex.getInstance().get(shortName, project, allScope).asSequence()
|
||||
|
||||
val descriptors = functions.asSequence()
|
||||
val descriptors = (functions + classes)
|
||||
.filter { it.fqName == targetFqName }
|
||||
.map { it.resolveToDescriptor(BodyResolveMode.PARTIAL) } // TODO Filter out not visible due dependencies config descriptors
|
||||
.toList()
|
||||
return descriptors
|
||||
if(descriptors.isNotEmpty())
|
||||
return descriptors
|
||||
|
||||
val packageDescriptors = collectAllModuleInfosFromIdeaModel(project)
|
||||
.asSequence()
|
||||
.map { resolutionFacade.findModuleDescriptor(it)?.getPackage(targetFqName) }
|
||||
.filterNotNull()
|
||||
.filterNot { it.isEmpty() }
|
||||
|
||||
return packageDescriptors.toList()
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -148,7 +148,7 @@ class KDocNameCompletionSession(
|
||||
val qualifiedLink = kDocLink.getLinkText().split('.').dropLast(1)
|
||||
val nameFilter = descriptorNameFilter.toNameFilter()
|
||||
if (qualifiedLink.isNotEmpty()) {
|
||||
val parentDescriptors = resolveKDocLink(bindingContext, resolutionFacade, declarationDescriptor, null, qualifiedLink)
|
||||
val parentDescriptors = resolveKDocLink(bindingContext, resolutionFacade, declarationDescriptor, kDocLink.getTagIfSubject(), qualifiedLink)
|
||||
val childDescriptorsOfPartialLink = parentDescriptors.asSequence().flatMap {
|
||||
val scope = getKDocLinkResolutionScope(resolutionFacade, it)
|
||||
collectDescriptorsFromScope(scope, nameFilter, false)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @sample samples.SampleGroup.mySample
|
||||
* @sample samples.megasamples.MegaSamplesGroup.megaSample
|
||||
* @sample samples.notindir.NotInDirSamples.sssample
|
||||
* @sample smaplez.a.b.c.Samplez.sssample
|
||||
*/
|
||||
fun some<caret>() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> some(): Unit <i>defined in</i> root package</pre><br/>
|
||||
//INFO: <dl><dt><b>Samples:</b></dt><dd><a href="psi_element://samples.SampleGroup.mySample"><code>samples.SampleGroup.mySample</code></a><pre><code>
|
||||
//INFO: println("Hello, world")
|
||||
//INFO: </code></pre></dd><dd><a href="psi_element://samples.megasamples.MegaSamplesGroup.megaSample"><code>samples.megasamples.MegaSamplesGroup.megaSample</code></a><pre><code>
|
||||
//INFO: println("...---...")
|
||||
//INFO: </code></pre></dd><dd><a href="psi_element://samples.notindir.NotInDirSamples.sssample"><code>samples.notindir.NotInDirSamples.sssample</code></a><pre><code>
|
||||
//INFO: println("location is samplesTest/")
|
||||
//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>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package samples.notindir
|
||||
|
||||
object NotInDirSamples {
|
||||
fun sssample() {
|
||||
println("location is samplesTest/")
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package samples.megasamples
|
||||
|
||||
object MegaSamplesGroup {
|
||||
fun megaSample() {
|
||||
println("...---...")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package samples
|
||||
|
||||
object SampleGroup {
|
||||
fun mySample() {
|
||||
println("Hello, world")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package samplez.a.b.c
|
||||
|
||||
object Samplez {
|
||||
fun sssample() {
|
||||
println("samplez")
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,13 @@ import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
|
||||
import com.intellij.rt.execution.junit.FileComparisonFailure
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.editor.quickDoc.AbstractQuickDocProviderTest.wrapToFileComparisonFailure
|
||||
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
@@ -44,10 +49,47 @@ class KDocSampleTest : AbstractMultiModuleTest() {
|
||||
|
||||
samples.addDependency(code)
|
||||
|
||||
doTest("simple/code/usage.kt")
|
||||
doInfoTest("simple/code/usage.kt")
|
||||
}
|
||||
|
||||
fun doTest(path: String) {
|
||||
fun testFqName() {
|
||||
|
||||
val code = module("code")
|
||||
val samples = module("samples", hasTestRoot = true)
|
||||
|
||||
samples.addDependency(code)
|
||||
|
||||
doInfoTest("fqName/code/usage.kt")
|
||||
doResolveTest("fqName/code/usage.kt", "samples")
|
||||
doResolveTest("fqName/code/usage.kt", "samples.SampleGroup")
|
||||
doResolveTest("fqName/code/usage.kt", "samples.megasamples")
|
||||
doResolveTest("fqName/code/usage.kt", "samples.megasamples.MegaSamplesGroup")
|
||||
doResolveTest("fqName/code/usage.kt", "samples.notindir")
|
||||
doResolveTest("fqName/code/usage.kt", "samples.notindir.NotInDirSamples")
|
||||
doResolveTest("fqName/code/usage.kt", "samplez")
|
||||
doResolveTest("fqName/code/usage.kt", "samplez.a")
|
||||
doResolveTest("fqName/code/usage.kt", "samplez.a.b")
|
||||
doResolveTest("fqName/code/usage.kt", "samplez.a.b.c")
|
||||
doResolveTest("fqName/code/usage.kt", "samplez.a.b.c.Samplez")
|
||||
}
|
||||
|
||||
fun doResolveTest(path: String, link: String) {
|
||||
|
||||
configureByFile(path)
|
||||
val documentationManager = DocumentationManager.getInstance(myProject)
|
||||
val targetElement = documentationManager.findTargetElement(myEditor, file)
|
||||
|
||||
targetElement as KtElement
|
||||
|
||||
val bindingContext = targetElement.analyze()
|
||||
val descriptor = bindingContext[DECLARATION_TO_DESCRIPTOR, targetElement]!!
|
||||
val kdoc = descriptor.findKDoc()!! as KDocSection
|
||||
val resolutionFacade = targetElement.getResolutionFacade()
|
||||
assertNotEmpty(resolveKDocLink(bindingContext, resolutionFacade, descriptor, kdoc.findTagByName("sample")!!, link.split(".")))
|
||||
|
||||
}
|
||||
|
||||
fun doInfoTest(path: String) {
|
||||
val testDataFile = File(testPath, path)
|
||||
configureByFile(path)
|
||||
val documentationManager = DocumentationManager.getInstance(myProject)
|
||||
@@ -77,11 +119,11 @@ class KDocSampleTest : AbstractMultiModuleTest() {
|
||||
|
||||
if (expectedInfo.endsWith("...\n")) {
|
||||
if (!info!!.startsWith(expectedInfo.removeSuffix("...\n"))) {
|
||||
wrapToFileComparisonFailure(info, testDataPath, textData)
|
||||
wrapToFileComparisonFailure(info, testDataFile.absolutePath, textData)
|
||||
}
|
||||
}
|
||||
else if (expectedInfo != info) {
|
||||
wrapToFileComparisonFailure(info, path, textData)
|
||||
wrapToFileComparisonFailure(info!!, testDataFile.absolutePath, textData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user