From aeb2014eee704be377c06205d16f60562d2a8cf1 Mon Sep 17 00:00:00 2001 From: Błażej Kardyś Date: Fri, 17 Jul 2020 03:48:03 +0200 Subject: Fixing javadoc comment parser for psi files --- .../kotlin/content/params/ContentForParamsTest.kt | 54 +++---- .../content/seealso/ContentForSeeAlsoTest.kt | 34 +++-- .../SkippingParenthesisForConstructorsTest.kt | 2 +- plugins/base/src/test/kotlin/enums/EnumsTest.kt | 4 +- .../transformers/CommentsToContentConverterTest.kt | 164 ++++++++++++--------- .../test/kotlin/translators/JavadocParserTest.kt | 156 ++++++++++++++++++++ plugins/base/src/test/kotlin/translators/utils.kt | 42 ++++-- 7 files changed, 336 insertions(+), 120 deletions(-) create mode 100644 plugins/base/src/test/kotlin/translators/JavadocParserTest.kt (limited to 'plugins/base/src/test') diff --git a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt index a9689bc5..4ac5717d 100644 --- a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt +++ b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt @@ -86,7 +86,7 @@ class ContentForParamsTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - pWrapped("comment to function") + group { pWrapped("comment to function") } } divergent { bareSignature( @@ -131,8 +131,8 @@ class ContentForParamsTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - unnamedTag("Author") { +"Kordyjan" } - unnamedTag("Since") { +"0.11" } + unnamedTag("Author") { group { +"Kordyjan" } } + unnamedTag("Since") { group { +"0.11" } } } divergent { bareSignature( @@ -178,9 +178,9 @@ class ContentForParamsTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - pWrapped("comment to function") - unnamedTag("Author") { +"Kordyjan" } - unnamedTag("Since") { +"0.11" } + group { pWrapped("comment to function") } + unnamedTag("Author") { group { +"Kordyjan" } } + unnamedTag("Since") { group { +"0.11" } } } divergent { bareSignature( @@ -225,14 +225,14 @@ class ContentForParamsTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - pWrapped("comment to function") + group { pWrapped("comment to function") } header(2) { +"Parameters" } group { platformHinted { table { group { +"abc" - group { +"comment to param" } + group { group { +"comment to param" } } } } } @@ -283,22 +283,22 @@ class ContentForParamsTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - pWrapped("comment to function") + group { group { group { +"comment to function" } } } header(2) { +"Parameters" } group { platformHinted { table { group { +"first" - group { +"comment to first param" } + group { group { +"comment to first param" } } } group { +"second" - group { +"comment to second param" } + group { group { +"comment to second param" } } } group { +"third" - group { +"comment to third param" } + group { group { +"comment to third param" } } } } } @@ -351,15 +351,15 @@ class ContentForParamsTest : AbstractCoreTest() { table { group { +"first" - group { +"comment to first param" } + group { group { +"comment to first param" } } } group { +"second" - group { +"comment to second param" } + group { group { +"comment to second param" } } } group { +"third" - group { +"comment to third param" } + group { group { +"comment to third param" } } } } } @@ -406,18 +406,18 @@ class ContentForParamsTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - pWrapped("comment to function") + group { pWrapped("comment to function") } header(2) { +"Parameters" } group { platformHinted { table { group { +"" - group { +"comment to receiver" } + group { group { +"comment to receiver" } } } group { +"abc" - group { +"comment to param" } + group { group { +"comment to param" } } } } } @@ -468,18 +468,18 @@ class ContentForParamsTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - pWrapped("comment to function") + group { group { group { +"comment to function" } } } header(2) { +"Parameters" } group { platformHinted { table { group { +"first" - group { +"comment to first param" } + group { group { +"comment to first param" } } } group { +"third" - group { +"comment to third param" } + group { group { +"comment to third param" } } } } } @@ -529,9 +529,9 @@ class ContentForParamsTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - pWrapped("comment to function") - unnamedTag("Author") { +"Kordyjan" } - unnamedTag("Since") { +"0.11" } + group { pWrapped("comment to function") } + unnamedTag("Author") { group { +"Kordyjan" } } + unnamedTag("Since") { group { +"0.11" } } header(2) { +"Parameters" } group { @@ -539,15 +539,15 @@ class ContentForParamsTest : AbstractCoreTest() { table { group { +"first" - group { +"comment to first param" } + group { group { +"comment to first param" } } } group { +"second" - group { +"comment to second param" } + group { group { +"comment to second param" } } } group { +"third" - group { +"comment to third param" } + group { group { +"comment to third param" } } } } } diff --git a/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt b/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt index 24970660..fd51c895 100644 --- a/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt +++ b/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt @@ -89,7 +89,7 @@ class ContentForSeeAlsoTest : AbstractCoreTest() { group { //DRI should be "test//abc/#/-1/" link { +"abc" } - group { } + group { group { } } } } } @@ -144,7 +144,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() { group { //DRI should be "test//abc/#/-1/" link { +"abc" } - group { +"Comment to abc" } + group { + group { +"Comment to abc" } + } } } } @@ -199,7 +201,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() { group { //DRI should be "kotlin.collections/Collection////" link { +"Collection" } - group { } + group { + group { } + } } } } @@ -254,7 +258,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() { group { //DRI should be "test//abc/#/-1/" link { +"Collection" } - group { +"Comment to stdliblink" } + group { + group { +"Comment to stdliblink" } + } } } } @@ -305,9 +311,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() { divergentGroup { divergentInstance { before { - pWrapped("random comment") - unnamedTag("Author") { +"pikinier20" } - unnamedTag("Since") { +"0.11" } + group { group { group { +"random comment"} } } + unnamedTag("Author") { group { +"pikinier20" } } + unnamedTag("Since") { group { +"0.11" } } header(2) { +"See also" } group { @@ -316,7 +322,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() { group { //DRI should be "test//abc/#/-1/" link { +"Collection" } - group { +"Comment to stdliblink" } + group { + group { +"Comment to stdliblink" } + } } } } @@ -372,7 +380,9 @@ class ContentForSeeAlsoTest : AbstractCoreTest() { group { //DRI should be "test//abc/#/-1/" link { +"abc" } - group { +"Comment to abc2" } + group { + group { +"Comment to abc2" } + } } } } @@ -428,12 +438,14 @@ class ContentForSeeAlsoTest : AbstractCoreTest() { group { //DRI should be "test//abc/#/-1/" link { +"abc" } - group { +"Comment to abc1" } + group { + group { +"Comment to abc1" } + } } group { //DRI should be "test//abc/#/-1/" link { +"Collection" } - group { +"Comment to collection" } + group { group { +"Comment to collection" } } } } } diff --git a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt index 90a38055..b3da3f71 100644 --- a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt +++ b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt @@ -230,7 +230,7 @@ class ConstructorsSignaturesTest : AbstractCoreTest() { platformHinted { group { group { - +"ctor comment" + group { +"ctor comment" } } } group { diff --git a/plugins/base/src/test/kotlin/enums/EnumsTest.kt b/plugins/base/src/test/kotlin/enums/EnumsTest.kt index 6a973f8e..9cd41dcd 100644 --- a/plugins/base/src/test/kotlin/enums/EnumsTest.kt +++ b/plugins/base/src/test/kotlin/enums/EnumsTest.kt @@ -210,7 +210,9 @@ class EnumsTest : AbstractCoreTest() { platformHinted { group { group { - + "Sample docs for E1" + group { + +"Sample docs for E1" + } } } group { diff --git a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt index 5197afc6..ad023d84 100644 --- a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt +++ b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt @@ -37,7 +37,7 @@ class CommentsToContentConverterTest { fun `simple text`() { val docTag = P(listOf(Text("This is simple test of string Next line"))) executeTest(docTag) { - +"This is simple test of string Next line" + group { +"This is simple test of string Next line" } } } @@ -51,9 +51,11 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - +"This is simple test of string" - node() - +"Next line" + group { + +"This is simple test of string" + node() + +"Next line" + } } } @@ -66,10 +68,14 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - +"Paragraph number one" - +"Paragraph" - node() - +"number two" + group { + group { +"Paragraph number one" } + group { + +"Paragraph" + node() + +"number two" + } + } } } @@ -122,20 +128,22 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - node { - group { +"Outer first Outer next line" } - group { +"Outer second" } + group { node { - group { +"Middle first Middle next line" } - group { +"Middle second" } + group { +"Outer first Outer next line" } + group { +"Outer second" } node { - group { +"Inner first Inner next line" } + group { +"Middle first Middle next line" } + group { +"Middle second" } + node { + group { +"Inner first Inner next line" } + } + group { +"Middle third" } } - group { +"Middle third" } + group { +"Outer third" } } - group { +"Outer third" } + group { +"New paragraph" } } - +"New paragraph" } } @@ -149,9 +157,11 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - header(1) { +"Header 1" } - +"Following text" - +"New paragraph" + group { + header(1) { +"Header 1" } + group { +"Following text" } + group { +"New paragraph" } + } } } @@ -174,18 +184,20 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - header(1) {+"Header 1"} - +"Text 1" - header(2) {+"Header 2"} - +"Text 2" - header(3) {+"Header 3"} - +"Text 3" - header(4) {+"Header 4"} - +"Text 4" - header(5) {+"Header 5"} - +"Text 5" - header(6) {+"Header 6"} - +"Text 6" + group { + header(1) { +"Header 1" } + group { +"Text 1" } + header(2) { +"Header 2" } + group { +"Text 2" } + header(3) { +"Header 3" } + group { +"Text 3" } + header(4) { +"Header 4" } + group { +"Text 4" } + header(5) { +"Header 5" } + group { +"Text 5" } + header(6) { +"Header 6" } + group { +"Text 6" } + } } } @@ -211,12 +223,14 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - node { - +"Blockquotes are very handy in email to emulate reply text. This line is part of the same quote." - } - +"Quote break." - node { - +"Quote" + group { + node { + +"Blockquotes are very handy in email to emulate reply text. This line is part of the same quote." + } + group { +"Quote break." } + node { + +"Quote" + } } } } @@ -245,16 +259,18 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - node { - +"text 1 text 2" + group { node { - +"text 3 text 4" + +"text 1 text 2" + node { + +"text 3 text 4" + } + +"text 5" + } + group { +"Quote break." } + node { + +"Quote" } - +"text 5" - } - +"Quote break." - node { - +"Quote" } } } @@ -278,21 +294,23 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - node { - +"val x: Int = 0" - node() - +"val y: String = \"Text\"" - node() - node() - +" val z: Boolean = true" - node() - +"for(i in 0..10) {" - node() - +" println(i)" - node() - +"}" + group { + node { + +"val x: Int = 0" + node() + +"val y: String = \"Text\"" + node() + node() + +" val z: Boolean = true" + node() + +"for(i in 0..10) {" + node() + +" println(i)" + node() + +"}" + } + group { +"Sample text" } } - +"Sample text" } } @@ -307,7 +325,7 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - link { + group { link { +"I'm an inline-style link" check { assertEquals( @@ -315,7 +333,7 @@ class CommentsToContentConverterTest { "https://www.google.com" ) } - } + } } } } @@ -384,20 +402,24 @@ class CommentsToContentConverterTest { ) ) executeTest(docTag) { - node { - group { +"Outer first Outer next line" } - group { +"Outer second" } + group { node { - group { +"Middle first Middle next line" } - group { +"Middle second" } + group { +"Outer first Outer next line" } + group { +"Outer second" } node { - +"Inner first Inner next line" + group { +"Middle first Middle next line" } + group { +"Middle second" } + node { + +"Inner first Inner next line" + } + group { +"Middle third" } } - group { +"Middle third" } + group { +"Outer third" } + } + group { + +"New paragraph" } - group { +"Outer third" } } - +"New paragraph" } } } \ No newline at end of file diff --git a/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt b/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt new file mode 100644 index 00000000..a1fbb2a0 --- /dev/null +++ b/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt @@ -0,0 +1,156 @@ +package translators + +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.model.DModule +import org.jetbrains.dokka.model.childrenOfType +import org.jetbrains.dokka.model.doc.* +import org.jetbrains.dokka.model.firstChildOfType +import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.* +import utils.text + +class JavadocParserTest : AbstractCoreTest() { + + private fun performJavadocTest(testOperation: (DModule) -> Unit) { + val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/main/java") + } + } + } + + testInline( + """ + |/src/main/java/sample/Date2.java + |/** + | * The class Date represents a specific instant + | * in time, with millisecond precision. + | *

+ | * Prior to JDK 1.1, the class Date had two additional + | * functions. It allowed the interpretation of dates as year, month, day, hour, + | * minute, and second values. It also allowed the formatting and parsing + | * of date strings. Unfortunately, the API for these functions was not + | * amenable to internationalization. As of JDK 1.1, the + | * Calendar class should be used to convert between dates and time + | * fields and the DateFormat class should be used to format and + | * parse date strings. + | * The corresponding methods in Date are deprecated. + | *

+ | * Although the Date class is intended to reflect + | * coordinated universal time (UTC), it may not do so exactly, + | * depending on the host environment of the Java Virtual Machine. + | * Nearly all modern operating systems assume that 1 day = + | * 24 × 60 × 60 = 86400 seconds + | * in all cases. In UTC, however, about once every year or two there + | * is an extra second, called a "leap second." The leap + | * second is always added as the last second of the day, and always + | * on December 31 or June 30. For example, the last minute of the + | * year 1995 was 61 seconds long, thanks to an added leap second. + | * Most computer clocks are not accurate enough to be able to reflect + | * the leap-second distinction. + | *

+ | * Some computer standards are defined in terms of Greenwich mean + | * time (GMT), which is equivalent to universal time (UT). GMT is + | * the "civil" name for the standard; UT is the + | * "scientific" name for the same standard. The + | * distinction between UTC and UT is that UTC is based on an atomic + | * clock and UT is based on astronomical observations, which for all + | * practical purposes is an invisibly fine hair to split. Because the + | * earth's rotation is not uniform (it slows down and speeds up + | * in complicated ways), UT does not always flow uniformly. Leap + | * seconds are introduced as needed into UTC so as to keep UTC within + | * 0.9 seconds of UT1, which is a version of UT with certain + | * corrections applied. There are other time and date systems as + | * well; for example, the time scale used by the satellite-based + | * global positioning system (GPS) is synchronized to UTC but is + | * not adjusted for leap seconds. An interesting source of + | * further information is the U.S. Naval Observatory, particularly + | * the Directorate of Time at: + | *

+            | *     http://tycho.usno.navy.mil
+            | * 
+ | *

+ | * and their definitions of "Systems of Time" at: + | *

+            | *     http://tycho.usno.navy.mil/systime.html
+            | * 
+ | *

+ | * In all methods of class Date that accept or return + | * year, month, date, hours, minutes, and seconds values, the + | * following representations are used: + | *

    + | *
  • A year y is represented by the integer + | * y - 1900. + | *
  • A month is represented by an integer from 0 to 11; 0 is January, + | * 1 is February, and so forth; thus 11 is December. + | *
  • A date (day of month) is represented by an integer from 1 to 31 + | * in the usual manner. + | *
  • An hour is represented by an integer from 0 to 23. Thus, the hour + | * from midnight to 1 a.m. is hour 0, and the hour from noon to 1 + | * p.m. is hour 12. + | *
  • A minute is represented by an integer from 0 to 59 in the usual manner. + | *
  • A second is represented by an integer from 0 to 61; the values 60 and + | * 61 occur only for leap seconds and even then only in Java + | * implementations that actually track leap seconds correctly. Because + | * of the manner in which leap seconds are currently introduced, it is + | * extremely unlikely that two leap seconds will occur in the same + | * minute, but this specification follows the date and time conventions + | * for ISO C. + | *
+ | *

+ | * In all cases, arguments given to methods for these purposes need + | * not fall within the indicated ranges; for example, a date may be + | * specified as January 32 and is interpreted as meaning February 1. + | * + | * @author James Gosling + | * @author Arthur van Hoff + | * @author Alan Liu + | * @see java.text.DateFormat + | * @see java.util.Calendar + | * @since JDK1.0 + | * @apiSince 1 + | */ + |public class Date2 implements java.io.Serializable, java.lang.Cloneable, java.lang.Comparable { + | void x() { } + |} + """.trimIndent(), + configuration + ) { + documentablesMergingStage = testOperation + } + } + + @Test + fun `correctly parsed list`() { + performJavadocTest { module -> + val dateDescription = module.descriptionOf("Date2")!! + assertEquals(6, dateDescription.firstChildOfType

    ().children.filterIsInstance
  • ().size) + } + } + + @Test + fun `correctly parsed author tags`() { + performJavadocTest { module -> + val authors = module.findClasslike().documentation.values.single().childrenOfType() + assertEquals(3, authors.size) + assertEquals("James Gosling", authors[0].firstChildOfType().text()) + assertEquals("Arthur van Hoff", authors[1].firstChildOfType().text()) + assertEquals("Alan Liu", authors[2].firstChildOfType().text()) + } + } + + @Test + fun `correctly parsed see tags`() { + performJavadocTest { module -> + val sees = module.findClasslike().documentation.values.single().childrenOfType() + assertEquals(2, sees.size) + assertEquals(DRI("java.text", "DateFormat"), sees[0].address) + assertEquals("java.text.DateFormat", sees[0].name) + assertEquals(DRI("java.util", "Calendar"), sees[1].address) + assertEquals("java.util.Calendar", sees[1].name) + } + } +} diff --git a/plugins/base/src/test/kotlin/translators/utils.kt b/plugins/base/src/test/kotlin/translators/utils.kt index 96d3035a..71b4a28b 100644 --- a/plugins/base/src/test/kotlin/translators/utils.kt +++ b/plugins/base/src/test/kotlin/translators/utils.kt @@ -1,16 +1,40 @@ package translators -import org.jetbrains.dokka.model.DModule +import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.doc.Description import org.jetbrains.dokka.model.doc.Text +import java.util.NoSuchElementException -fun DModule.documentationOf(className: String, functionName: String): String { - return (packages.single() - .classlikes.single { it.name == className } - .functions.single { it.name == functionName } - .documentation.values.singleOrNull() - ?.children?.singleOrNull() - .run { this as? Description } - ?.root?.children?.single() as? Text) +fun DModule.documentationOf(className: String, functionName: String? = null): String = + descriptionOf(className, functionName) + ?.firstChildOfType() ?.body.orEmpty() + +fun DModule.descriptionOf(className: String, functionName: String? = null): Description? { + val classlike = packages.single() + .classlikes.single { it.name == className } + val target: Documentable = + if (functionName != null) classlike.functions.single { it.name == functionName } else classlike + return target.documentation.values.singleOrNull() + ?.firstChildOfTypeOrNull() +} + +fun DModule.findPackage(packageName: String? = null) = + packageName?.let { packages.firstOrNull { pkg -> pkg.name == packageName } + ?: throw NoSuchElementException("No packageName with name $packageName") } ?: packages.single() + +fun DModule.findClasslike(packageName: String? = null, className: String? = null): DClasslike { + val pkg = findPackage(packageName) + return className?.let { + pkg.classlikes.firstOrNull { cls -> cls.name == className } + ?: throw NoSuchElementException("No classlike with name $className") + } ?: pkg.classlikes.single() +} + +fun DModule.findFunction(packageName: String? = null, className: String, functionName: String? = null): DFunction { + val classlike = findClasslike(packageName, className) + return functionName?.let { + classlike.functions.firstOrNull { fn -> fn.name == functionName } + ?: throw NoSuchElementException("No classlike with name $functionName") + } ?: classlike.functions.single() } \ No newline at end of file -- cgit