diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocReference.kt index 5d9338ef87c..81bb80ba68a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocReference.kt @@ -16,38 +16,24 @@ package org.jetbrains.kotlin.idea.kdoc -import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink import com.intellij.openapi.util.TextRange -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.idea.references.JetMultiReference -import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag -import org.jetbrains.kotlin.descriptors.CallableDescriptor import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.descriptors.DeclarationDescriptorNonRoot -import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.descriptors.PackageViewDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.resolve.scopes.RedeclarationHandler -import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl -import org.jetbrains.kotlin.resolve.scopes.WritableScope -import org.jetbrains.kotlin.resolve.scopes.ChainedScope -import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil -import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils -import org.jetbrains.kotlin.kdoc.psi.impl.KDocName -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService -import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer -import org.jetbrains.kotlin.resolve.source.PsiSourceElement -import org.jetbrains.kotlin.psi.JetFile -import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource +import org.jetbrains.kotlin.idea.references.JetMultiReference import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag -import com.intellij.psi.PsiReference -import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink +import org.jetbrains.kotlin.kdoc.psi.impl.KDocName +import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.JetFile +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil +import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer +import org.jetbrains.kotlin.resolve.scopes.* +import org.jetbrains.kotlin.resolve.source.PsiSourceElement +import org.jetbrains.kotlin.utils.Printer public class KDocReference(element: KDocName): JetMultiReference(element) { override fun getTargetDescriptors(context: BindingContext): Collection { @@ -87,9 +73,23 @@ public fun resolveKDocLink(session: KotlinCodeAnalyzer, return resolveParamLink(fromDescriptor, qualifiedName) } + // Try to find a matching local descriptor (parameter or type parameter) first. + if (qualifiedName.size() == 1) { + val scope = getResolutionScope(session, fromDescriptor) + val localResult = scope.getDescriptors().filter { + it.getName().asString() == qualifiedName.single() && it.getContainingDeclaration() == fromDescriptor + } + if (!localResult.isEmpty()) { + return localResult + } + } + var result: Collection = listOf(fromDescriptor) qualifiedName.forEach { nameComponent -> if (result.size() != 1) return listOf() + if (!Name.isValidIdentifier(nameComponent)) { + return listOf() + } val scope = getResolutionScope(session, result.first()) result = scope.getDescriptors().filter { it.getName().asString() == nameComponent } } diff --git a/idea/testData/kdoc/resolve/AmbiguousReference.kt b/idea/testData/kdoc/resolve/AmbiguousReference.kt new file mode 100644 index 00000000000..fc0f1c605b8 --- /dev/null +++ b/idea/testData/kdoc/resolve/AmbiguousReference.kt @@ -0,0 +1,12 @@ +class C { + fun f1() { + } + + /** + * The [f1] references a parameter. + */ + fun f2(f1: String) { + } +} + +// REF: f1 diff --git a/idea/testData/kdoc/resolve/AmbiguousReferenceTypeParameter.kt b/idea/testData/kdoc/resolve/AmbiguousReferenceTypeParameter.kt new file mode 100644 index 00000000000..dd47c88c7f3 --- /dev/null +++ b/idea/testData/kdoc/resolve/AmbiguousReferenceTypeParameter.kt @@ -0,0 +1,12 @@ +class C { + class TT { + } + + /** + * The [TT] references a type parameter. + */ + class D { + } +} + +// REF: TT diff --git a/idea/tests/org/jetbrains/kotlin/idea/kdoc/KdocResolveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/kdoc/KdocResolveTestGenerated.java index aa0abb78f64..f226b94e648 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/kdoc/KdocResolveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/kdoc/KdocResolveTestGenerated.java @@ -37,6 +37,18 @@ public class KdocResolveTestGenerated extends AbstractReferenceResolveTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/kdoc/resolve"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("AmbiguousReference.kt") + public void testAmbiguousReference() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/AmbiguousReference.kt"); + doTest(fileName); + } + + @TestMetadata("AmbiguousReferenceTypeParameter.kt") + public void testAmbiguousReferenceTypeParameter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/AmbiguousReferenceTypeParameter.kt"); + doTest(fileName); + } + @TestMetadata("ClassSelfReference.kt") public void testClassSelfReference() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ClassSelfReference.kt");