Fix for KT-7995 Quick doc should show deprecation info and ReplaceWith
This commit is contained in:
committed by
Simon Ogorodnik
parent
1a211ee7b0
commit
3376dbb10d
@@ -36,13 +36,21 @@ private val JAVA_DEPRECATED = FqName("java.lang.Deprecated")
|
||||
|
||||
interface Deprecation {
|
||||
val deprecationLevel: DeprecationLevelValue
|
||||
val message: String
|
||||
val message: String?
|
||||
val target: DeclarationDescriptor
|
||||
}
|
||||
|
||||
fun Deprecation.deprecatedByOverriddenMessage(): String? = (this as? DeprecatedByOverridden)?.additionalMessage()
|
||||
|
||||
private data class DeprecatedByAnnotation(private val annotation: AnnotationDescriptor, override val target: DeclarationDescriptor) : Deprecation {
|
||||
fun Deprecation.deprecatedByAnnotationReplaceWithExpression(): String? {
|
||||
val annotation = (this as? DeprecatedByAnnotation)?.annotation ?: return null
|
||||
val replaceWithAnnotation = annotation.argumentValue(kotlin.Deprecated::replaceWith.name)
|
||||
as? AnnotationDescriptor ?: return null
|
||||
|
||||
return replaceWithAnnotation.argumentValue(kotlin.ReplaceWith::expression.name) as String
|
||||
}
|
||||
|
||||
private data class DeprecatedByAnnotation(val annotation: AnnotationDescriptor, override val target: DeclarationDescriptor) : Deprecation {
|
||||
override val deprecationLevel: DeprecationLevelValue
|
||||
get() {
|
||||
val level = annotation.argumentValue("level") as? ClassDescriptor
|
||||
@@ -55,8 +63,8 @@ private data class DeprecatedByAnnotation(private val annotation: AnnotationDesc
|
||||
}
|
||||
}
|
||||
|
||||
override val message: String
|
||||
get() = annotation.argumentValue("message") as? String ?: ""
|
||||
override val message: String?
|
||||
get() = annotation.argumentValue("message") as? String
|
||||
}
|
||||
|
||||
private data class DeprecatedByOverridden(private val deprecations: Collection<Deprecation>) : Deprecation {
|
||||
@@ -184,7 +192,7 @@ internal fun createDeprecationDiagnostic(element: PsiElement, deprecation: Depre
|
||||
ERROR -> Errors.DEPRECATION_ERROR
|
||||
HIDDEN -> Errors.DEPRECATION_ERROR
|
||||
}
|
||||
return diagnosticFactory.on(element, targetOriginal, deprecation.message)
|
||||
return diagnosticFactory.on(element, targetOriginal, deprecation.message ?: "")
|
||||
}
|
||||
|
||||
// values from kotlin.DeprecationLevel
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import com.google.common.html.HtmlEscapers
|
||||
import com.intellij.codeInsight.documentation.DocumentationManagerUtil
|
||||
import com.intellij.lang.documentation.AbstractDocumentationProvider
|
||||
import com.intellij.lang.java.JavaDocumentationProvider
|
||||
@@ -41,7 +42,9 @@ 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.deprecatedByAnnotationReplaceWithExpression
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.getDeprecation
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.constant
|
||||
|
||||
@@ -153,6 +156,9 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
|
||||
if (!quickNavigation) {
|
||||
renderedDecl = "<pre>$renderedDecl</pre>"
|
||||
}
|
||||
|
||||
renderedDecl += renderDeprecationInfo(declarationDescriptor)
|
||||
|
||||
val comment = declarationDescriptor.findKDoc()
|
||||
if (comment != null) {
|
||||
val renderedComment = KDocRenderer.renderKDoc(comment)
|
||||
@@ -167,6 +173,39 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
|
||||
return renderedDecl
|
||||
}
|
||||
|
||||
private fun renderDeprecationInfo(declarationDescriptor: DeclarationDescriptor): String {
|
||||
val deprecation = declarationDescriptor.getDeprecation() ?: return ""
|
||||
|
||||
return buildString {
|
||||
wrapTag("DL") {
|
||||
deprecation.message?.let { message ->
|
||||
wrapTag("DT") { wrapTag("b") { append("Deprecated:") } }
|
||||
wrapTag("DD") {
|
||||
append(message.htmlEscape())
|
||||
}
|
||||
}
|
||||
deprecation.deprecatedByAnnotationReplaceWithExpression()?.let { replaceWith ->
|
||||
wrapTag("DT") { wrapTag("b") { append("Replace with:") } }
|
||||
wrapTag("DD") {
|
||||
wrapTag("code") { append(replaceWith.htmlEscape()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun String.htmlEscape(): String = HtmlEscapers.htmlEscaper().escape(this)
|
||||
|
||||
private inline fun StringBuilder.wrap(prefix: String, postfix: String, crossinline body: () -> Unit) {
|
||||
this.append(prefix)
|
||||
body()
|
||||
this.append(postfix)
|
||||
}
|
||||
|
||||
private inline fun StringBuilder.wrapTag(tag: String, crossinline body: () -> Unit) {
|
||||
wrap("<$tag>", "</$tag>", body)
|
||||
}
|
||||
|
||||
private fun mixKotlinToJava(declarationDescriptor: DeclarationDescriptor, element: PsiElement, originalElement: PsiElement?): String? {
|
||||
val originalInfo = JavaDocumentationProvider().getQuickNavigateInfo(element, originalElement)
|
||||
if (originalInfo != null) {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
@Deprecated("lol no more mainstream", replaceWith = ReplaceWith(expression = "kek()"))
|
||||
fun <caret>lol() {
|
||||
println("lol")
|
||||
}
|
||||
|
||||
//INFO: @<a href="psi_element://kotlin.Deprecated">Deprecated</a> <b>public</b> <b>fun</b> lol(): Unit <i>defined in</i> root package<DL><DT><b>Deprecated:</b></DT><DD>lol no more mainstream</DD><DT><b>Replace with:</b></DT><DD><code>kek()</code></DD></DL>
|
||||
+6
@@ -72,6 +72,12 @@ public class QuickDocProviderTestGenerated extends AbstractQuickDocProviderTest
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DeprecationWithReplaceInfo.kt")
|
||||
public void testDeprecationWithReplaceInfo() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/DeprecationWithReplaceInfo.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("EscapeHtmlInsideCodeBlocks.kt")
|
||||
public void testEscapeHtmlInsideCodeBlocks() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/EscapeHtmlInsideCodeBlocks.kt");
|
||||
|
||||
Reference in New Issue
Block a user