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 {
|
interface Deprecation {
|
||||||
val deprecationLevel: DeprecationLevelValue
|
val deprecationLevel: DeprecationLevelValue
|
||||||
val message: String
|
val message: String?
|
||||||
val target: DeclarationDescriptor
|
val target: DeclarationDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Deprecation.deprecatedByOverriddenMessage(): String? = (this as? DeprecatedByOverridden)?.additionalMessage()
|
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
|
override val deprecationLevel: DeprecationLevelValue
|
||||||
get() {
|
get() {
|
||||||
val level = annotation.argumentValue("level") as? ClassDescriptor
|
val level = annotation.argumentValue("level") as? ClassDescriptor
|
||||||
@@ -55,8 +63,8 @@ private data class DeprecatedByAnnotation(private val annotation: AnnotationDesc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val message: String
|
override val message: String?
|
||||||
get() = annotation.argumentValue("message") as? String ?: ""
|
get() = annotation.argumentValue("message") as? String
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class DeprecatedByOverridden(private val deprecations: Collection<Deprecation>) : Deprecation {
|
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
|
ERROR -> Errors.DEPRECATION_ERROR
|
||||||
HIDDEN -> 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
|
// values from kotlin.DeprecationLevel
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea
|
package org.jetbrains.kotlin.idea
|
||||||
|
|
||||||
|
import com.google.common.html.HtmlEscapers
|
||||||
import com.intellij.codeInsight.documentation.DocumentationManagerUtil
|
import com.intellij.codeInsight.documentation.DocumentationManagerUtil
|
||||||
import com.intellij.lang.documentation.AbstractDocumentationProvider
|
import com.intellij.lang.documentation.AbstractDocumentationProvider
|
||||||
import com.intellij.lang.java.JavaDocumentationProvider
|
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.ClassifierNamePolicy
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.deprecatedByAnnotationReplaceWithExpression
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
|
import org.jetbrains.kotlin.resolve.getDeprecation
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.constant
|
import org.jetbrains.kotlin.utils.addToStdlib.constant
|
||||||
|
|
||||||
@@ -153,6 +156,9 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
if (!quickNavigation) {
|
if (!quickNavigation) {
|
||||||
renderedDecl = "<pre>$renderedDecl</pre>"
|
renderedDecl = "<pre>$renderedDecl</pre>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderedDecl += renderDeprecationInfo(declarationDescriptor)
|
||||||
|
|
||||||
val comment = declarationDescriptor.findKDoc()
|
val comment = declarationDescriptor.findKDoc()
|
||||||
if (comment != null) {
|
if (comment != null) {
|
||||||
val renderedComment = KDocRenderer.renderKDoc(comment)
|
val renderedComment = KDocRenderer.renderKDoc(comment)
|
||||||
@@ -167,6 +173,39 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
|
|||||||
return renderedDecl
|
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? {
|
private fun mixKotlinToJava(declarationDescriptor: DeclarationDescriptor, element: PsiElement, originalElement: PsiElement?): String? {
|
||||||
val originalInfo = JavaDocumentationProvider().getQuickNavigateInfo(element, originalElement)
|
val originalInfo = JavaDocumentationProvider().getQuickNavigateInfo(element, originalElement)
|
||||||
if (originalInfo != null) {
|
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);
|
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")
|
@TestMetadata("EscapeHtmlInsideCodeBlocks.kt")
|
||||||
public void testEscapeHtmlInsideCodeBlocks() throws Exception {
|
public void testEscapeHtmlInsideCodeBlocks() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/EscapeHtmlInsideCodeBlocks.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/EscapeHtmlInsideCodeBlocks.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user