diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/j2k/IdeaDocCommentConverter.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/j2k/IdeaDocCommentConverter.kt index 96dd5fcf969..955c30ddb3e 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/j2k/IdeaDocCommentConverter.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/j2k/IdeaDocCommentConverter.kt @@ -73,7 +73,7 @@ object IdeaDocCommentConverter : DocCommentConverter { return this } - private fun convertInlineDocTag(tag: PsiInlineDocTag) = when(tag.name) { + private fun convertInlineDocTag(tag: PsiInlineDocTag) = when (tag.name) { "code", "literal" -> { val text = tag.dataElements.joinToString("") { it.text } val escaped = StringUtil.escapeXml(text.trimStart()) @@ -92,11 +92,17 @@ object IdeaDocCommentConverter : DocCommentConverter { } private fun convertJavadocLink(link: String?): String = - if (link != null) link.substringBefore('(').replace('#', '.') else "" + if (link != null) link.substringBefore('(').replace('#', '.') else "" private fun PsiDocTag.linkElement(): PsiElement? = valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace } + private fun XmlTag.attributesAsString() = + if (attributes.isNotEmpty()) + attributes.joinToString(separator = " ", prefix = " ") { it.text } + else + "" + private class HtmlToMarkdownConverter() : XmlRecursiveElementVisitor() { private enum class ListType { Ordered, Unordered; } data class MarkdownSpan(val prefix: String, val suffix: String) { @@ -105,6 +111,9 @@ object IdeaDocCommentConverter : DocCommentConverter { fun wrap(text: String) = MarkdownSpan(text, text) fun prefix(text: String) = MarkdownSpan(text, "") + + fun preserveTag(tag: XmlTag) = + MarkdownSpan("<${tag.name}${tag.attributesAsString()}>", "") } } @@ -142,7 +151,7 @@ object IdeaDocCommentConverter : DocCommentConverter { XmlTokenType.XML_CHAR_ENTITY_REF -> { appendPendingText() val grandParent = element.parent.parent - if(grandParent is HtmlTag && (grandParent.name == "code" || grandParent.name == "literal")) + if (grandParent is HtmlTag && (grandParent.name == "code" || grandParent.name == "literal")) markdownBuilder.append(StringUtil.unescapeXml(element.text)) else markdownBuilder.append(element.text) @@ -183,7 +192,7 @@ object IdeaDocCommentConverter : DocCommentConverter { } } - private fun getMarkdownForTag(tag: XmlTag, atLineStart: Boolean): MarkdownSpan = when(tag.name) { + private fun getMarkdownForTag(tag: XmlTag, atLineStart: Boolean): MarkdownSpan = when (tag.name) { "b", "strong" -> MarkdownSpan.wrap("**") "p" -> if (atLineStart) MarkdownSpan.prefix("\n * ") else MarkdownSpan.prefix("\n *\n *") @@ -200,22 +209,29 @@ object IdeaDocCommentConverter : DocCommentConverter { val innerText = tag.value.text if (docRef == innerText) MarkdownSpan("[", "]") else MarkdownSpan("[", "][$docRef]") } + else if (tag.getAttributeValue("href") != null) { + MarkdownSpan("[", "](${tag.getAttributeValue("href") ?: ""})") + } else { - MarkdownSpan("[", "](${tag.getAttributeValue("href")})") + MarkdownSpan.preserveTag(tag) } } - "ul" -> { currentListType = ListType.Unordered; MarkdownSpan.Empty } + "ul" -> { + currentListType = ListType.Unordered; MarkdownSpan.Empty + } - "ol" -> { currentListType = ListType.Ordered; MarkdownSpan.Empty } + "ol" -> { + currentListType = ListType.Ordered; MarkdownSpan.Empty + } "li" -> if (currentListType == ListType.Unordered) MarkdownSpan.prefix(" * ") else MarkdownSpan.prefix(" 1. ") - else -> MarkdownSpan.Empty + else -> MarkdownSpan.preserveTag(tag) } private fun appendPendingText() { - if (afterLineBreak ) { + if (afterLineBreak) { markdownBuilder.append(" * ") afterLineBreak = false } diff --git a/j2k/testData/fileOrElement/docComments/aWithoutHref.java b/j2k/testData/fileOrElement/docComments/aWithoutHref.java new file mode 100644 index 00000000000..692d50ac295 --- /dev/null +++ b/j2k/testData/fileOrElement/docComments/aWithoutHref.java @@ -0,0 +1,7 @@ +/** + * Important + * Just an link without href + */ +public class A { + +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/docComments/aWithoutHref.kt b/j2k/testData/fileOrElement/docComments/aWithoutHref.kt new file mode 100644 index 00000000000..523222f9ff4 --- /dev/null +++ b/j2k/testData/fileOrElement/docComments/aWithoutHref.kt @@ -0,0 +1,5 @@ +/** + * Important + * Just an link without href + */ +class A \ No newline at end of file diff --git a/j2k/testData/fileOrElement/docComments/escapedCharactersInCodeQuote.java b/j2k/testData/fileOrElement/docComments/escapedCharactersInCodeQuote.java new file mode 100644 index 00000000000..f9dc0de4401 --- /dev/null +++ b/j2k/testData/fileOrElement/docComments/escapedCharactersInCodeQuote.java @@ -0,0 +1,5 @@ +/** + * {@code A<B} + */ +public class C { +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/docComments/escapedCharactersInCodeQuote.kt b/j2k/testData/fileOrElement/docComments/escapedCharactersInCodeQuote.kt new file mode 100644 index 00000000000..717254677a1 --- /dev/null +++ b/j2k/testData/fileOrElement/docComments/escapedCharactersInCodeQuote.kt @@ -0,0 +1,4 @@ +/** + * `A<B` + */ +class C \ No newline at end of file diff --git a/j2k/testData/fileOrElement/docComments/preserveUnknownTags.java b/j2k/testData/fileOrElement/docComments/preserveUnknownTags.java new file mode 100644 index 00000000000..e5905919507 --- /dev/null +++ b/j2k/testData/fileOrElement/docComments/preserveUnknownTags.java @@ -0,0 +1,9 @@ +/** + * Doc comment.

+ * cited

+ * spanned

+ * !!! + */ +public class A { + +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/docComments/preserveUnknownTags.kt b/j2k/testData/fileOrElement/docComments/preserveUnknownTags.kt new file mode 100644 index 00000000000..ca958324d7c --- /dev/null +++ b/j2k/testData/fileOrElement/docComments/preserveUnknownTags.kt @@ -0,0 +1,13 @@ +/** + * Doc comment. + * + * + * cited + * + * + * spanned + * + * + * !!! + */ +class A \ No newline at end of file diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index a8103154d58..7c65621dc9c 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -1719,6 +1719,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class DocComments extends AbstractJavaToKotlinConverterForWebDemoTest { + @TestMetadata("aWithoutHref.java") + public void testAWithoutHref() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/aWithoutHref.java"); + doTest(fileName); + } + public void testAllFilesPresentInDocComments() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/fileOrElement/docComments"), Pattern.compile("^(.+)\\.java$"), true); } @@ -1735,6 +1741,13 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("escapedCharactersInCodeQuote.java") + public void testEscapedCharactersInCodeQuote() throws Exception { + String fileName = + KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/escapedCharactersInCodeQuote.java"); + doTest(fileName); + } + @TestMetadata("htmlInDocComment.java") public void testHtmlInDocComment() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/htmlInDocComment.java"); @@ -1765,6 +1778,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("preserveUnknownTags.java") + public void testPreserveUnknownTags() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/preserveUnknownTags.java"); + doTest(fileName); + } + @TestMetadata("quoted.java") public void testQuoted() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/quoted.java"); diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index a22e98f7731..e3794beb98f 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -1719,6 +1719,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class DocComments extends AbstractJavaToKotlinConverterSingleFileTest { + @TestMetadata("aWithoutHref.java") + public void testAWithoutHref() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/aWithoutHref.java"); + doTest(fileName); + } + public void testAllFilesPresentInDocComments() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/fileOrElement/docComments"), Pattern.compile("^(.+)\\.java$"), true); } @@ -1735,6 +1741,13 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("escapedCharactersInCodeQuote.java") + public void testEscapedCharactersInCodeQuote() throws Exception { + String fileName = + KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/escapedCharactersInCodeQuote.java"); + doTest(fileName); + } + @TestMetadata("htmlInDocComment.java") public void testHtmlInDocComment() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/htmlInDocComment.java"); @@ -1765,6 +1778,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("preserveUnknownTags.java") + public void testPreserveUnknownTags() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/preserveUnknownTags.java"); + doTest(fileName); + } + @TestMetadata("quoted.java") public void testQuoted() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/docComments/quoted.java");