Feature KT-7739 Type names in Quick Documentation should be clickable and navigate to their documentation

Filter out 'boring builtin classifiers' (kotlin.Int for ex) from signature hyperlinks
This commit is contained in:
Simon Ogorodnik
2016-11-09 19:20:48 +03:00
parent 68d4a7abce
commit c93e47febf
7 changed files with 76 additions and 4 deletions
@@ -16,12 +16,14 @@
package org.jetbrains.kotlin.idea
import com.intellij.codeInsight.documentation.DocumentationManagerUtil
import com.intellij.lang.documentation.AbstractDocumentationProvider
import com.intellij.lang.java.JavaDocumentationProvider
import com.intellij.openapi.diagnostic.Logger
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
@@ -30,6 +32,7 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
import org.jetbrains.kotlin.idea.kdoc.KDocRenderer
import org.jetbrains.kotlin.idea.kdoc.findKDoc
import org.jetbrains.kotlin.idea.kdoc.isBoringBuiltinClass
import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.*
@@ -38,9 +41,22 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.renderer.ClassifierNamePolicy
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.utils.addToStdlib.constant
class HtmlClassifierNamePolicy(val base: ClassifierNamePolicy) : ClassifierNamePolicy {
override fun renderClassifier(classifier: ClassifierDescriptor, renderer: DescriptorRenderer): String {
val name = base.renderClassifier(classifier, renderer)
if (classifier.isBoringBuiltinClass())
return name
return buildString {
val ref = classifier.fqNameUnsafe.toString()
DocumentationManagerUtil.createHyperlink(this, ref, name, true)
}
}
}
class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
override fun getQuickNavigateInfo(element: PsiElement?, originalElement: PsiElement?): String? {
@@ -72,7 +88,7 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
private val LOG = Logger.getInstance(KotlinQuickDocumentationProvider::class.java)
private val DESCRIPTOR_RENDERER = DescriptorRenderer.HTML.withOptions {
classifierNamePolicy = ClassifierNamePolicy.SHORT
classifierNamePolicy = HtmlClassifierNamePolicy(ClassifierNamePolicy.SHORT)
renderCompanionObjectName = true
}
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.kdoc
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils
private val boringBuiltinClasses = setOf(
FQ_NAMES.unit,
FQ_NAMES._byte,
FQ_NAMES._short,
FQ_NAMES._int,
FQ_NAMES._long,
FQ_NAMES._char,
FQ_NAMES._boolean,
FQ_NAMES._float,
FQ_NAMES._double,
FQ_NAMES.string,
FQ_NAMES.array,
FQ_NAMES.any
)
fun ClassifierDescriptor.isBoringBuiltinClass(): Boolean =
DescriptorUtils.getFqName(this) in boringBuiltinClasses
+1 -1
View File
@@ -2,4 +2,4 @@ interface Base
class Some<<caret>T: Base>
//INFO: &lt;T : Base&gt; <i>defined in</i> Some
//INFO: &lt;T : <a href="psi_element://Base">Base</a>&gt; <i>defined in</i> Some
+1 -1
View File
@@ -2,4 +2,4 @@ fun testing() {
<caret>SomeClass<List<String>>()
}
// INFO: <b>public</b> <b>constructor</b> SomeClass&lt;T : (MutableList&lt;Any?&gt;..List&lt;*&gt;?)&gt;()<br/>Java declaration:<br/>[light_idea_test_case] public class SomeClass&lt;T extends java.util.List&gt; extends Object
//INFO: <b>public</b> <b>constructor</b> SomeClass&lt;T : (<(raw) Any?>&lt;Any?&gt;..<(raw) Any?>&lt;*&gt;?)&gt;()<br/>Java declaration:<br/>[light_idea_test_case] public class SomeClass&lt;T extends java.util.List&gt; extends Object
+1 -1
View File
@@ -2,4 +2,4 @@ fun test() {
listOf(1, 2, 4).<caret>filter { it > 0 }
}
//INFO: <b>public</b> inline <b>fun</b> &lt;T&gt; Iterable&lt;T&gt;.filter(predicate: (T) &rarr; Boolean): List&lt;T&gt; <i>defined in</i> kotlin.collections<p>Returns a list containing only elements matching the given <a href="psi_element://predicate">predicate</a>.</p>
//INFO: <b>public</b> inline <b>fun</b> &lt;T&gt; <a href="psi_element://kotlin.collections.Iterable">Iterable</a>&lt;<a href="psi_element://kotlin.collections.filter.T">T</a>&gt;.filter(predicate: (<a href="psi_element://kotlin.collections.filter.T">T</a>) &rarr; Boolean): <a href="psi_element://kotlin.collections.List">List</a>&lt;<a href="psi_element://kotlin.collections.filter.T">T</a>&gt; <i>defined in</i> kotlin.collections<p>Returns a list containing only elements matching the given <a href="psi_element://predicate">predicate</a>.</p>
@@ -0,0 +1,11 @@
class A {
}
fun foo(x : A) { }
fun main(args: Array<String>) {
<caret>foo()
}
//INFO: <b>public</b> <b>fun</b> foo(x: <a href="psi_element://A">A</a>): Unit <i>defined in</i> root package
@@ -197,4 +197,10 @@ public class QuickDocProviderTestGenerated extends AbstractQuickDocProviderTest
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/TopLevelMethodFromJava.java");
doTest(fileName);
}
@TestMetadata("TypeNamesFromStdLibNavigation.kt")
public void testTypeNamesFromStdLibNavigation() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/TypeNamesFromStdLibNavigation.kt");
doTest(fileName);
}
}