tdochelpers.nim 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. discard """
  2. matrix: "--mm:refc; --mm:orc"
  3. output: '''
  4. [Suite] Integration with Nim
  5. '''
  6. """
  7. # tests for dochelpers.nim module
  8. import ../../lib/packages/docutils/[rstast, rst, dochelpers]
  9. import unittest
  10. import std/assertions
  11. proc testMsgHandler(filename: string, line, col: int, msgkind: MsgKind,
  12. arg: string) =
  13. doAssert msgkind == mwBrokenLink
  14. proc fromRst(text: string): LangSymbol =
  15. let r = rstParse(text, "-input-", LineRstInit, ColRstInit,
  16. {roNimFile},
  17. msgHandler=testMsgHandler)
  18. assert r.node.kind == rnRstRef
  19. result = toLangSymbol(r.node)
  20. proc fromMd(text: string): LangSymbol =
  21. let r = rstParse(text, "-input-", LineRstInit, ColRstInit,
  22. {roPreferMarkdown, roSupportMarkdown, roNimFile},
  23. msgHandler=testMsgHandler)
  24. assert r.node.kind == rnPandocRef
  25. assert r.node.len == 2
  26. # this son is the target:
  27. assert r.node.sons[1].kind == rnInner
  28. result = toLangSymbol(r.node.sons[1])
  29. suite "Integration with Nim":
  30. test "simple symbol parsing (shortest form)":
  31. let expected = LangSymbol(symKind: "", name: "g")
  32. check "g_".fromRst == expected
  33. check "[g]".fromMd == expected
  34. # test also alternative syntax variants of Pandoc Markdown:
  35. check "[g][]".fromMd == expected
  36. check "[this symbol][g]".fromMd == expected
  37. test "simple symbol parsing (group of words)":
  38. #let input1 = "`Y`_".rstParseTest
  39. let expected1 = LangSymbol(symKind: "", name: "Y")
  40. check "`Y`_".fromRst == expected1
  41. check "[Y]".fromMd == expected1
  42. # this means not a statement 'type', it's a backticked identifier `type`:
  43. let expected2 = LangSymbol(symKind: "", name: "type")
  44. check "`type`_".fromRst == expected2
  45. check "[type]".fromMd == expected2
  46. let expected3 = LangSymbol(symKind: "", name: "[]")
  47. check "`[]`_".fromRst == expected3
  48. # Markdown syntax for this case is NOT [[]]
  49. check "[`[]`]".fromMd == expected3
  50. let expected4 = LangSymbol(symKind: "", name: "Xyz")
  51. check "`X Y Z`_".fromRst == expected4
  52. check "[X Y Z]".fromMd == expected4
  53. test "simple proc parsing":
  54. let expected = LangSymbol(symKind: "proc", name: "f")
  55. check "`proc f`_".fromRst == expected
  56. check "[proc f]".fromMd == expected
  57. test "another backticked name":
  58. let expected = LangSymbol(symKind: "template", name: "type")
  59. check """`template \`type\``_""".fromRst == expected
  60. # no backslash in Markdown:
  61. check """[template `type`]""".fromMd == expected
  62. test "simple proc parsing with parameters":
  63. let expected = LangSymbol(symKind: "proc", name: "f",
  64. parametersProvided: true)
  65. check "`proc f*()`_".fromRst == expected
  66. check "`proc f()`_".fromRst == expected
  67. check "[proc f*()]".fromMd == expected
  68. check "[proc f()]".fromMd == expected
  69. test "symbol parsing with 1 parameter":
  70. let expected = LangSymbol(symKind: "", name: "f",
  71. parameters: @[("G[int]", "")],
  72. parametersProvided: true)
  73. check "`f(G[int])`_".fromRst == expected
  74. check "[f(G[int])]".fromMd == expected
  75. test "more proc parsing":
  76. let input1 = "`proc f[T](x:G[T]):M[T]`_".fromRst
  77. let input2 = "`proc f[ T ] ( x: G [T] ): M[T]`_".fromRst
  78. let input3 = "`proc f*[T](x: G[T]): M[T]`_".fromRst
  79. let expected = LangSymbol(symKind: "proc",
  80. name: "f",
  81. generics: "[T]",
  82. parameters: @[("x", "G[T]")],
  83. parametersProvided: true,
  84. outType: "M[T]")
  85. check(input1 == expected)
  86. check(input2 == expected)
  87. check(input3 == expected)
  88. test "advanced proc parsing with Nim identifier normalization":
  89. let inputRst = """`proc binarySearch*[T, K](a: openarray[T]; key: K;
  90. cmp: proc (x: T; y: K): int)`_"""
  91. let inputMd = """[proc binarySearch*[T, K](a: openarray[T]; key: K;
  92. cmp: proc (x: T; y: K): int)]"""
  93. let expected = LangSymbol(symKind: "proc",
  94. name: "binarysearch",
  95. generics: "[T,K]",
  96. parameters: @[
  97. ("a", "openarray[T]"),
  98. ("key", "K"),
  99. ("cmp", "proc(x:T;y:K):int")],
  100. parametersProvided: true,
  101. outType: "")
  102. check(inputRst.fromRst == expected)
  103. check(inputMd.fromMd == expected)
  104. test "the same without proc":
  105. let input = """`binarySearch*[T, K](a: openarray[T]; key: K;
  106. cmp: proc (x: T; y: K): int {.closure.})`_"""
  107. let expected = LangSymbol(symKind: "",
  108. name: "binarysearch",
  109. generics: "[T,K]",
  110. parameters: @[
  111. ("a", "openarray[T]"),
  112. ("key", "K"),
  113. ("cmp", "proc(x:T;y:K):int")],
  114. parametersProvided: true,
  115. outType: "")
  116. check(input.fromRst == expected)
  117. let inputMd = """[binarySearch*[T, K](a: openarray[T]; key: K;
  118. cmp: proc (x: T; y: K): int {.closure.})]"""
  119. check(inputMd.fromMd == expected)
  120. test "operator $ with and without backticks":
  121. let input1 = """`func \`$\`*[T](a: \`open Array\`[T]): string`_"""
  122. let input1md = "[func `$`*[T](a: `open Array`[T]): string]"
  123. let input2 = """`func $*[T](a: \`open Array\`[T]): string`_"""
  124. let input2md = "[func $*[T](a: `open Array`[T]): string]"
  125. let expected = LangSymbol(symKind: "func",
  126. name: "$",
  127. generics: "[T]",
  128. parameters: @[("a", "openarray[T]")],
  129. parametersProvided: true,
  130. outType: "string")
  131. check input1.fromRst == expected
  132. check input2.fromRst == expected
  133. check input1md.fromMd == expected
  134. check input2md.fromMd == expected
  135. test "operator [] with and without backticks":
  136. let input1 = """`func \`[]\`[T](a: \`open Array\`[T], idx: int): T`_"""
  137. let input1md = "[func `[]`[T](a: `open Array`[T], idx: int): T]"
  138. let input2 = """`func [][T](a: \`open Array\`[T], idx: int): T`_"""
  139. let input2md = "[func [][T](a: `open Array`[T], idx: int): T]"
  140. let expected = LangSymbol(symKind: "func",
  141. name: "[]",
  142. generics: "[T]",
  143. parameters: @[("a", "openarray[T]"),
  144. ("idx", "int")],
  145. parametersProvided: true,
  146. outType: "T")
  147. check input1.fromRst == expected
  148. check input2.fromRst == expected
  149. check input1md.fromMd == expected
  150. check input2md.fromMd == expected
  151. test "postfix symbol specifier #1":
  152. let input = "`walkDir iterator`_"
  153. let inputMd = "[walkDir iterator]"
  154. let expected = LangSymbol(symKind: "iterator",
  155. name: "walkdir")
  156. check input.fromRst == expected
  157. check inputMd.fromMd == expected
  158. test "postfix symbol specifier #2":
  159. let input1 = """`\`[]\`[T](a: \`open Array\`[T], idx: int): T func`_"""
  160. let input1md = "[`[]`[T](a: `open Array`[T], idx: int): T func]"
  161. let input2 = """`[][T](a: \`open Array\`[T], idx: int): T func`_"""
  162. # note again that ` is needed between 1st and second [
  163. let input2md = "[`[]`[T](a: `open Array`[T], idx: int): T func]"
  164. let expected = LangSymbol(symKind: "func",
  165. name: "[]",
  166. generics: "[T]",
  167. parameters: @[("a", "openarray[T]"),
  168. ("idx", "int")],
  169. parametersProvided: true,
  170. outType: "T")
  171. check input1.fromRst == expected
  172. check input2.fromRst == expected
  173. check input1md.fromMd == expected
  174. check input2md.fromMd == expected
  175. test "type of type":
  176. let inputRst = "`CopyFlag enum`_"
  177. let inputMd = "[CopyFlag enum]"
  178. let expected = LangSymbol(symKind: "type",
  179. symTypeKind: "enum",
  180. name: "Copyflag")
  181. check inputRst.fromRst == expected
  182. check inputMd.fromMd == expected
  183. test "prefixed module":
  184. let inputRst = "`module std / paths`_"
  185. let inputMd = "[module std / paths]"
  186. let expected = LangSymbol(symKind: "module",
  187. name: "std/paths")
  188. check inputRst.fromRst == expected
  189. check inputMd.fromMd == expected
  190. test "postfixed module":
  191. let inputRst = "`std / paths module`_"
  192. let inputMd = "[std / paths module]"
  193. let expected = LangSymbol(symKind: "module",
  194. name: "std/paths")
  195. check inputRst.fromRst == expected
  196. check inputMd.fromMd == expected