From c93e47febf07490a8670fc7bd8de83236398ed5b Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 9 Nov 2016 19:20:48 +0300 Subject: [PATCH] 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 --- .../idea/KotlinQuickDocumentationProvider.kt | 18 ++++++++- .../kotlin/idea/kdoc/kdocBoringClassifiers.kt | 39 +++++++++++++++++++ .../editor/quickDoc/AtTypeParameter.kt | 2 +- .../editor/quickDoc/JavaClassUsedInKotlin.kt | 2 +- .../editor/quickDoc/MethodFromStdLib.kt | 2 +- .../quickDoc/TypeNamesFromStdLibNavigation.kt | 11 ++++++ .../QuickDocProviderTestGenerated.java | 6 +++ 7 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/kdoc/kdocBoringClassifiers.kt create mode 100644 idea/testData/editor/quickDoc/TypeNamesFromStdLibNavigation.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt b/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt index f8ed15683be..ec88231d69a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt @@ -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 } diff --git a/idea/src/org/jetbrains/kotlin/idea/kdoc/kdocBoringClassifiers.kt b/idea/src/org/jetbrains/kotlin/idea/kdoc/kdocBoringClassifiers.kt new file mode 100644 index 00000000000..e57aa8c131a --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/kdoc/kdocBoringClassifiers.kt @@ -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 \ No newline at end of file diff --git a/idea/testData/editor/quickDoc/AtTypeParameter.kt b/idea/testData/editor/quickDoc/AtTypeParameter.kt index a3642f959d5..7aa73d71d78 100644 --- a/idea/testData/editor/quickDoc/AtTypeParameter.kt +++ b/idea/testData/editor/quickDoc/AtTypeParameter.kt @@ -2,4 +2,4 @@ interface Base class Some<T: Base> -//INFO: <T : Base> defined in Some +//INFO: <T : Base> defined in Some diff --git a/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt b/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt index 44e6aa4fdd6..110b681e276 100644 --- a/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt +++ b/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt @@ -2,4 +2,4 @@ fun testing() { SomeClass>() } -// INFO: public constructor SomeClass<T : (MutableList<Any?>..List<*>?)>()
Java declaration:
[light_idea_test_case] public class SomeClass<T extends java.util.List> extends Object \ No newline at end of file +//INFO: public constructor SomeClass<T : (<(raw) Any?><Any?>..<(raw) Any?><*>?)>()
Java declaration:
[light_idea_test_case] public class SomeClass<T extends java.util.List> extends Object diff --git a/idea/testData/editor/quickDoc/MethodFromStdLib.kt b/idea/testData/editor/quickDoc/MethodFromStdLib.kt index e07071140f2..b1daded16be 100644 --- a/idea/testData/editor/quickDoc/MethodFromStdLib.kt +++ b/idea/testData/editor/quickDoc/MethodFromStdLib.kt @@ -2,4 +2,4 @@ fun test() { listOf(1, 2, 4).filter { it > 0 } } -//INFO: public inline fun <T> Iterable<T>.filter(predicate: (T) → Boolean): List<T> defined in kotlin.collections

Returns a list containing only elements matching the given predicate.

+//INFO: public inline fun <T> Iterable<T>.filter(predicate: (T) → Boolean): List<T> defined in kotlin.collections

Returns a list containing only elements matching the given predicate.

diff --git a/idea/testData/editor/quickDoc/TypeNamesFromStdLibNavigation.kt b/idea/testData/editor/quickDoc/TypeNamesFromStdLibNavigation.kt new file mode 100644 index 00000000000..378d061b225 --- /dev/null +++ b/idea/testData/editor/quickDoc/TypeNamesFromStdLibNavigation.kt @@ -0,0 +1,11 @@ +class A { + +} + +fun foo(x : A) { } + +fun main(args: Array) { + foo() +} + +//INFO: public fun foo(x: A): Unit defined in root package diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocProviderTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocProviderTestGenerated.java index 1265adf88bd..20e39bcc053 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocProviderTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocProviderTestGenerated.java @@ -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); + } }