yard 0.9.16 → 0.9.17

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of yard might be problematic. Click here for more details.

Files changed (566) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +26 -26
  3. data/CHANGELOG.md +728 -728
  4. data/LEGAL +66 -66
  5. data/LICENSE +22 -22
  6. data/README.md +328 -328
  7. data/Rakefile +53 -47
  8. data/benchmarks/builtins_vs_eval.rb +24 -24
  9. data/benchmarks/concat_vs_join.rb +13 -13
  10. data/benchmarks/erb_vs_erubis.rb +54 -54
  11. data/benchmarks/format_args.rb +47 -47
  12. data/benchmarks/generation.rb +38 -38
  13. data/benchmarks/marshal_vs_dbm.rb +64 -64
  14. data/benchmarks/parsing.rb +46 -46
  15. data/benchmarks/pathname_vs_string.rb +50 -50
  16. data/benchmarks/rdoc_vs_yardoc.rb +11 -11
  17. data/benchmarks/registry_store_types.rb +49 -49
  18. data/benchmarks/ri_vs_yri.rb +19 -19
  19. data/benchmarks/ripper_parser.rb +13 -13
  20. data/benchmarks/splat_vs_flatten.rb +13 -13
  21. data/benchmarks/template_erb.rb +23 -23
  22. data/benchmarks/template_format.rb +7 -7
  23. data/benchmarks/template_profile.rb +18 -18
  24. data/benchmarks/yri_cache.rb +20 -20
  25. data/bin/yard +13 -13
  26. data/bin/yardoc +13 -13
  27. data/bin/yri +13 -13
  28. data/docs/CodeObjects.md +115 -115
  29. data/docs/GettingStarted.md +679 -679
  30. data/docs/Handlers.md +152 -152
  31. data/docs/Overview.md +61 -61
  32. data/docs/Parser.md +191 -191
  33. data/docs/Tags.md +283 -283
  34. data/docs/TagsArch.md +123 -123
  35. data/docs/Templates.md +496 -496
  36. data/docs/WhatsNew.md +1245 -1245
  37. data/docs/templates/default/fulldoc/html/full_list_tag.erb +8 -8
  38. data/docs/templates/default/fulldoc/html/setup.rb +6 -6
  39. data/docs/templates/default/layout/html/setup.rb +9 -9
  40. data/docs/templates/default/layout/html/tag_list.erb +11 -11
  41. data/docs/templates/default/yard_tags/html/list.erb +18 -18
  42. data/docs/templates/default/yard_tags/html/setup.rb +26 -26
  43. data/docs/templates/plugin.rb +70 -70
  44. data/lib/rubygems_plugin.rb +9 -9
  45. data/lib/yard.rb +69 -69
  46. data/lib/yard/autoload.rb +303 -303
  47. data/lib/yard/cli/command.rb +85 -85
  48. data/lib/yard/cli/command_parser.rb +93 -93
  49. data/lib/yard/cli/config.rb +198 -198
  50. data/lib/yard/cli/diff.rb +270 -270
  51. data/lib/yard/cli/display.rb +69 -69
  52. data/lib/yard/cli/gems.rb +84 -84
  53. data/lib/yard/cli/graph.rb +125 -125
  54. data/lib/yard/cli/help.rb +20 -20
  55. data/lib/yard/cli/i18n.rb +70 -70
  56. data/lib/yard/cli/list.rb +23 -23
  57. data/lib/yard/cli/markup_types.rb +32 -32
  58. data/lib/yard/cli/server.rb +257 -257
  59. data/lib/yard/cli/stats.rb +231 -231
  60. data/lib/yard/cli/yardoc.rb +788 -788
  61. data/lib/yard/cli/yardopts_command.rb +110 -110
  62. data/lib/yard/cli/yri.rb +215 -215
  63. data/lib/yard/code_objects/base.rb +615 -610
  64. data/lib/yard/code_objects/class_object.rb +146 -146
  65. data/lib/yard/code_objects/class_variable_object.rb +11 -11
  66. data/lib/yard/code_objects/constant_object.rb +16 -16
  67. data/lib/yard/code_objects/extended_method_object.rb +24 -24
  68. data/lib/yard/code_objects/extra_file_object.rb +131 -131
  69. data/lib/yard/code_objects/macro_object.rb +172 -172
  70. data/lib/yard/code_objects/method_object.rb +196 -196
  71. data/lib/yard/code_objects/module_object.rb +21 -21
  72. data/lib/yard/code_objects/namespace_mapper.rb +114 -114
  73. data/lib/yard/code_objects/namespace_object.rb +200 -200
  74. data/lib/yard/code_objects/proxy.rb +240 -240
  75. data/lib/yard/code_objects/root_object.rb +19 -19
  76. data/lib/yard/config.rb +270 -270
  77. data/lib/yard/core_ext/array.rb +16 -16
  78. data/lib/yard/core_ext/file.rb +69 -69
  79. data/lib/yard/core_ext/hash.rb +16 -16
  80. data/lib/yard/core_ext/insertion.rb +63 -63
  81. data/lib/yard/core_ext/module.rb +20 -20
  82. data/lib/yard/core_ext/string.rb +68 -68
  83. data/lib/yard/core_ext/symbol_hash.rb +75 -75
  84. data/lib/yard/docstring.rb +386 -378
  85. data/lib/yard/docstring_parser.rb +345 -345
  86. data/lib/yard/gem_index.rb +29 -29
  87. data/lib/yard/globals.rb +22 -22
  88. data/lib/yard/handlers/base.rb +595 -595
  89. data/lib/yard/handlers/c/alias_handler.rb +16 -16
  90. data/lib/yard/handlers/c/attribute_handler.rb +13 -13
  91. data/lib/yard/handlers/c/base.rb +129 -129
  92. data/lib/yard/handlers/c/class_handler.rb +27 -27
  93. data/lib/yard/handlers/c/constant_handler.rb +13 -13
  94. data/lib/yard/handlers/c/handler_methods.rb +211 -211
  95. data/lib/yard/handlers/c/init_handler.rb +20 -20
  96. data/lib/yard/handlers/c/method_handler.rb +45 -36
  97. data/lib/yard/handlers/c/mixin_handler.rb +21 -21
  98. data/lib/yard/handlers/c/module_handler.rb +17 -17
  99. data/lib/yard/handlers/c/override_comment_handler.rb +31 -31
  100. data/lib/yard/handlers/c/path_handler.rb +11 -11
  101. data/lib/yard/handlers/c/struct_handler.rb +13 -13
  102. data/lib/yard/handlers/c/symbol_handler.rb +8 -8
  103. data/lib/yard/handlers/processor.rb +200 -200
  104. data/lib/yard/handlers/ruby/alias_handler.rb +44 -44
  105. data/lib/yard/handlers/ruby/attribute_handler.rb +87 -87
  106. data/lib/yard/handlers/ruby/base.rb +165 -165
  107. data/lib/yard/handlers/ruby/class_condition_handler.rb +92 -92
  108. data/lib/yard/handlers/ruby/class_handler.rb +119 -119
  109. data/lib/yard/handlers/ruby/class_variable_handler.rb +17 -17
  110. data/lib/yard/handlers/ruby/comment_handler.rb +10 -10
  111. data/lib/yard/handlers/ruby/constant_handler.rb +59 -59
  112. data/lib/yard/handlers/ruby/decorator_handler_methods.rb +123 -123
  113. data/lib/yard/handlers/ruby/dsl_handler.rb +15 -15
  114. data/lib/yard/handlers/ruby/dsl_handler_methods.rb +96 -95
  115. data/lib/yard/handlers/ruby/exception_handler.rb +27 -27
  116. data/lib/yard/handlers/ruby/extend_handler.rb +22 -22
  117. data/lib/yard/handlers/ruby/legacy/alias_handler.rb +37 -37
  118. data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +65 -65
  119. data/lib/yard/handlers/ruby/legacy/base.rb +245 -245
  120. data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +83 -83
  121. data/lib/yard/handlers/ruby/legacy/class_handler.rb +113 -113
  122. data/lib/yard/handlers/ruby/legacy/class_variable_handler.rb +15 -15
  123. data/lib/yard/handlers/ruby/legacy/comment_handler.rb +10 -10
  124. data/lib/yard/handlers/ruby/legacy/constant_handler.rb +29 -29
  125. data/lib/yard/handlers/ruby/legacy/dsl_handler.rb +17 -17
  126. data/lib/yard/handlers/ruby/legacy/exception_handler.rb +13 -13
  127. data/lib/yard/handlers/ruby/legacy/extend_handler.rb +21 -21
  128. data/lib/yard/handlers/ruby/legacy/method_handler.rb +90 -90
  129. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +39 -39
  130. data/lib/yard/handlers/ruby/legacy/module_function_handler.rb +19 -19
  131. data/lib/yard/handlers/ruby/legacy/module_handler.rb +12 -12
  132. data/lib/yard/handlers/ruby/legacy/private_class_method_handler.rb +22 -22
  133. data/lib/yard/handlers/ruby/legacy/private_constant_handler.rb +22 -22
  134. data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +17 -17
  135. data/lib/yard/handlers/ruby/legacy/yield_handler.rb +29 -29
  136. data/lib/yard/handlers/ruby/method_condition_handler.rb +9 -9
  137. data/lib/yard/handlers/ruby/method_handler.rb +118 -118
  138. data/lib/yard/handlers/ruby/mixin_handler.rb +37 -37
  139. data/lib/yard/handlers/ruby/module_function_handler.rb +27 -27
  140. data/lib/yard/handlers/ruby/module_handler.rb +12 -12
  141. data/lib/yard/handlers/ruby/private_class_method_handler.rb +14 -14
  142. data/lib/yard/handlers/ruby/private_constant_handler.rb +43 -43
  143. data/lib/yard/handlers/ruby/public_class_method_handler.rb +14 -14
  144. data/lib/yard/handlers/ruby/struct_handler_methods.rb +143 -143
  145. data/lib/yard/handlers/ruby/visibility_handler.rb +22 -22
  146. data/lib/yard/handlers/ruby/yield_handler.rb +31 -31
  147. data/lib/yard/i18n/locale.rb +67 -67
  148. data/lib/yard/i18n/message.rb +57 -57
  149. data/lib/yard/i18n/messages.rb +56 -56
  150. data/lib/yard/i18n/po_parser.rb +61 -61
  151. data/lib/yard/i18n/pot_generator.rb +290 -290
  152. data/lib/yard/i18n/text.rb +173 -173
  153. data/lib/yard/logging.rb +205 -205
  154. data/lib/yard/options.rb +217 -217
  155. data/lib/yard/parser/base.rb +57 -57
  156. data/lib/yard/parser/c/c_parser.rb +235 -235
  157. data/lib/yard/parser/c/comment_parser.rb +134 -134
  158. data/lib/yard/parser/c/statement.rb +64 -64
  159. data/lib/yard/parser/ruby/ast_node.rb +540 -540
  160. data/lib/yard/parser/ruby/legacy/ruby_lex.rb +1354 -1354
  161. data/lib/yard/parser/ruby/legacy/ruby_parser.rb +32 -32
  162. data/lib/yard/parser/ruby/legacy/statement.rb +66 -66
  163. data/lib/yard/parser/ruby/legacy/statement_list.rb +394 -394
  164. data/lib/yard/parser/ruby/legacy/token_list.rb +74 -74
  165. data/lib/yard/parser/ruby/ruby_parser.rb +687 -687
  166. data/lib/yard/parser/ruby/token_resolver.rb +156 -156
  167. data/lib/yard/parser/source_parser.rb +526 -526
  168. data/lib/yard/rake/yardoc_task.rb +81 -81
  169. data/lib/yard/registry.rb +439 -439
  170. data/lib/yard/registry_resolver.rb +189 -189
  171. data/lib/yard/registry_store.rb +337 -337
  172. data/lib/yard/rubygems/backports.rb +10 -10
  173. data/lib/yard/rubygems/backports/LICENSE.txt +57 -57
  174. data/lib/yard/rubygems/backports/MIT.txt +20 -20
  175. data/lib/yard/rubygems/backports/gem.rb +10 -10
  176. data/lib/yard/rubygems/backports/source_index.rb +365 -365
  177. data/lib/yard/rubygems/doc_manager.rb +90 -90
  178. data/lib/yard/rubygems/hook.rb +197 -197
  179. data/lib/yard/rubygems/specification.rb +50 -50
  180. data/lib/yard/serializers/base.rb +83 -83
  181. data/lib/yard/serializers/file_system_serializer.rb +123 -123
  182. data/lib/yard/serializers/process_serializer.rb +24 -24
  183. data/lib/yard/serializers/stdout_serializer.rb +34 -34
  184. data/lib/yard/serializers/yardoc_serializer.rb +152 -152
  185. data/lib/yard/server.rb +13 -13
  186. data/lib/yard/server/adapter.rb +100 -100
  187. data/lib/yard/server/commands/base.rb +209 -209
  188. data/lib/yard/server/commands/display_file_command.rb +29 -29
  189. data/lib/yard/server/commands/display_object_command.rb +65 -65
  190. data/lib/yard/server/commands/frames_command.rb +16 -16
  191. data/lib/yard/server/commands/library_command.rb +187 -187
  192. data/lib/yard/server/commands/library_index_command.rb +28 -28
  193. data/lib/yard/server/commands/list_command.rb +25 -25
  194. data/lib/yard/server/commands/root_request_command.rb +15 -15
  195. data/lib/yard/server/commands/search_command.rb +79 -79
  196. data/lib/yard/server/commands/static_file_command.rb +23 -23
  197. data/lib/yard/server/commands/static_file_helpers.rb +62 -62
  198. data/lib/yard/server/doc_server_helper.rb +91 -91
  199. data/lib/yard/server/doc_server_serializer.rb +39 -39
  200. data/lib/yard/server/library_version.rb +277 -277
  201. data/lib/yard/server/rack_adapter.rb +89 -89
  202. data/lib/yard/server/router.rb +187 -187
  203. data/lib/yard/server/static_caching.rb +46 -46
  204. data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +127 -127
  205. data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +11 -11
  206. data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +37 -37
  207. data/lib/yard/server/templates/default/layout/html/script_setup.erb +7 -7
  208. data/lib/yard/server/templates/default/layout/html/setup.rb +8 -8
  209. data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -4
  210. data/lib/yard/server/templates/default/method_details/html/setup.rb +5 -5
  211. data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +8 -8
  212. data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +14 -14
  213. data/lib/yard/server/templates/doc_server/library_list/html/listing.erb +13 -13
  214. data/lib/yard/server/templates/doc_server/library_list/html/setup.rb +6 -6
  215. data/lib/yard/server/templates/doc_server/library_list/html/title.erb +2 -2
  216. data/lib/yard/server/templates/doc_server/processing/html/processing.erb +52 -52
  217. data/lib/yard/server/templates/doc_server/processing/html/setup.rb +4 -4
  218. data/lib/yard/server/templates/doc_server/search/html/search.erb +18 -18
  219. data/lib/yard/server/templates/doc_server/search/html/setup.rb +9 -9
  220. data/lib/yard/server/webrick_adapter.rb +45 -45
  221. data/lib/yard/tags/default_factory.rb +191 -191
  222. data/lib/yard/tags/default_tag.rb +13 -13
  223. data/lib/yard/tags/directives.rb +616 -616
  224. data/lib/yard/tags/library.rb +633 -633
  225. data/lib/yard/tags/option_tag.rb +13 -13
  226. data/lib/yard/tags/overload_tag.rb +71 -71
  227. data/lib/yard/tags/ref_tag.rb +8 -8
  228. data/lib/yard/tags/ref_tag_list.rb +28 -28
  229. data/lib/yard/tags/tag.rb +71 -71
  230. data/lib/yard/tags/tag_format_error.rb +7 -7
  231. data/lib/yard/tags/types_explainer.rb +162 -162
  232. data/lib/yard/templates/engine.rb +186 -186
  233. data/lib/yard/templates/erb_cache.rb +23 -23
  234. data/lib/yard/templates/helpers/base_helper.rb +215 -215
  235. data/lib/yard/templates/helpers/filter_helper.rb +27 -27
  236. data/lib/yard/templates/helpers/html_helper.rb +646 -642
  237. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +78 -78
  238. data/lib/yard/templates/helpers/markup/rdoc_markdown.rb +23 -23
  239. data/lib/yard/templates/helpers/markup/rdoc_markup.rb +109 -109
  240. data/lib/yard/templates/helpers/markup_helper.rb +172 -172
  241. data/lib/yard/templates/helpers/method_helper.rb +75 -75
  242. data/lib/yard/templates/helpers/module_helper.rb +21 -21
  243. data/lib/yard/templates/helpers/text_helper.rb +112 -112
  244. data/lib/yard/templates/helpers/uml_helper.rb +47 -47
  245. data/lib/yard/templates/section.rb +105 -105
  246. data/lib/yard/templates/template.rb +418 -418
  247. data/lib/yard/templates/template_options.rb +92 -92
  248. data/lib/yard/verifier.rb +151 -151
  249. data/lib/yard/version.rb +3 -1
  250. data/spec/cli/command_parser_spec.rb +43 -43
  251. data/spec/cli/command_spec.rb +36 -36
  252. data/spec/cli/config_spec.rb +148 -148
  253. data/spec/cli/diff_spec.rb +254 -254
  254. data/spec/cli/display_spec.rb +30 -30
  255. data/spec/cli/gems_spec.rb +81 -81
  256. data/spec/cli/graph_spec.rb +18 -18
  257. data/spec/cli/help_spec.rb +22 -22
  258. data/spec/cli/i18n_spec.rb +107 -107
  259. data/spec/cli/list_spec.rb +8 -8
  260. data/spec/cli/markup_types_spec.rb +22 -22
  261. data/spec/cli/server_spec.rb +324 -324
  262. data/spec/cli/stats_spec.rb +96 -96
  263. data/spec/cli/yard_on_yard_spec.rb +38 -38
  264. data/spec/cli/yardoc_spec.rb +862 -849
  265. data/spec/cli/yri_spec.rb +101 -101
  266. data/spec/code_objects/base_spec.rb +470 -460
  267. data/spec/code_objects/class_object_spec.rb +226 -226
  268. data/spec/code_objects/code_object_list_spec.rb +36 -36
  269. data/spec/code_objects/constants_spec.rb +116 -116
  270. data/spec/code_objects/extra_file_object_spec.rb +160 -160
  271. data/spec/code_objects/macro_object_spec.rb +150 -150
  272. data/spec/code_objects/method_object_spec.rb +184 -184
  273. data/spec/code_objects/module_object_spec.rb +142 -142
  274. data/spec/code_objects/namespace_object_spec.rb +171 -171
  275. data/spec/code_objects/proxy_spec.rb +141 -141
  276. data/spec/code_objects/spec_helper.rb +3 -3
  277. data/spec/config_spec.rb +171 -171
  278. data/spec/core_ext/array_spec.rb +13 -13
  279. data/spec/core_ext/file_spec.rb +72 -72
  280. data/spec/core_ext/hash_spec.rb +14 -14
  281. data/spec/core_ext/insertion_spec.rb +37 -37
  282. data/spec/core_ext/module_spec.rb +15 -15
  283. data/spec/core_ext/string_spec.rb +42 -42
  284. data/spec/core_ext/symbol_hash_spec.rb +89 -89
  285. data/spec/docstring_parser_spec.rb +280 -262
  286. data/spec/docstring_spec.rb +373 -364
  287. data/spec/examples.txt +1875 -1871
  288. data/spec/handlers/alias_handler_spec.rb +82 -82
  289. data/spec/handlers/attribute_handler_spec.rb +96 -96
  290. data/spec/handlers/base_spec.rb +216 -216
  291. data/spec/handlers/c/alias_handler_spec.rb +34 -34
  292. data/spec/handlers/c/attribute_handler_spec.rb +41 -41
  293. data/spec/handlers/c/class_handler_spec.rb +78 -78
  294. data/spec/handlers/c/constant_handler_spec.rb +71 -71
  295. data/spec/handlers/c/init_handler_spec.rb +48 -48
  296. data/spec/handlers/c/method_handler_spec.rb +325 -325
  297. data/spec/handlers/c/mixin_handler_spec.rb +44 -44
  298. data/spec/handlers/c/module_handler_spec.rb +71 -71
  299. data/spec/handlers/c/override_comment_handler_spec.rb +47 -47
  300. data/spec/handlers/c/path_handler_spec.rb +36 -36
  301. data/spec/handlers/c/spec_helper.rb +23 -23
  302. data/spec/handlers/c/struct_handler_spec.rb +16 -16
  303. data/spec/handlers/class_condition_handler_spec.rb +87 -87
  304. data/spec/handlers/class_handler_spec.rb +247 -247
  305. data/spec/handlers/class_method_handler_shared_examples.rb +133 -133
  306. data/spec/handlers/class_variable_handler_spec.rb +12 -12
  307. data/spec/handlers/constant_handler_spec.rb +112 -112
  308. data/spec/handlers/decorator_handler_methods_spec.rb +393 -393
  309. data/spec/handlers/dsl_handler_spec.rb +219 -219
  310. data/spec/handlers/examples/alias_handler_001.rb.txt +45 -45
  311. data/spec/handlers/examples/attribute_handler_001.rb.txt +31 -31
  312. data/spec/handlers/examples/class_condition_handler_001.rb.txt +68 -68
  313. data/spec/handlers/examples/class_handler_001.rb.txt +120 -120
  314. data/spec/handlers/examples/class_variable_handler_001.rb.txt +9 -9
  315. data/spec/handlers/examples/constant_handler_001.rb.txt +35 -35
  316. data/spec/handlers/examples/dsl_handler_001.rb.txt +154 -154
  317. data/spec/handlers/examples/exception_handler_001.rb.txt +58 -58
  318. data/spec/handlers/examples/extend_handler_001.rb.txt +15 -15
  319. data/spec/handlers/examples/method_condition_handler_001.rb.txt +9 -9
  320. data/spec/handlers/examples/method_handler_001.rb.txt +128 -128
  321. data/spec/handlers/examples/mixin_handler_001.rb.txt +37 -37
  322. data/spec/handlers/examples/module_handler_001.rb.txt +29 -29
  323. data/spec/handlers/examples/private_constant_handler_001.rb.txt +8 -8
  324. data/spec/handlers/examples/process_handler_001.rb.txt +11 -11
  325. data/spec/handlers/examples/visibility_handler_001.rb.txt +35 -35
  326. data/spec/handlers/examples/yield_handler_001.rb.txt +54 -54
  327. data/spec/handlers/exception_handler_spec.rb +49 -49
  328. data/spec/handlers/extend_handler_spec.rb +24 -24
  329. data/spec/handlers/legacy_base_spec.rb +128 -128
  330. data/spec/handlers/method_condition_handler_spec.rb +15 -15
  331. data/spec/handlers/method_handler_spec.rb +190 -190
  332. data/spec/handlers/mixin_handler_spec.rb +56 -56
  333. data/spec/handlers/module_function_handler_spec.rb +106 -106
  334. data/spec/handlers/module_handler_spec.rb +35 -35
  335. data/spec/handlers/private_class_method_handler_spec.rb +11 -11
  336. data/spec/handlers/private_constant_handler_spec.rb +25 -25
  337. data/spec/handlers/processor_spec.rb +35 -35
  338. data/spec/handlers/public_class_method_handler_spec.rb +11 -11
  339. data/spec/handlers/ruby/base_spec.rb +95 -95
  340. data/spec/handlers/ruby/legacy/base_spec.rb +84 -84
  341. data/spec/handlers/spec_helper.rb +33 -33
  342. data/spec/handlers/visibility_handler_spec.rb +44 -44
  343. data/spec/handlers/yield_handler_spec.rb +52 -52
  344. data/spec/i18n/locale_spec.rb +81 -81
  345. data/spec/i18n/message_spec.rb +52 -52
  346. data/spec/i18n/messages_spec.rb +67 -67
  347. data/spec/i18n/pot_generator_spec.rb +295 -295
  348. data/spec/i18n/text_spec.rb +184 -184
  349. data/spec/logging_spec.rb +44 -44
  350. data/spec/options_spec.rb +171 -171
  351. data/spec/parser/base_spec.rb +24 -24
  352. data/spec/parser/c_parser_spec.rb +236 -223
  353. data/spec/parser/examples/array.c.txt +6267 -6267
  354. data/spec/parser/examples/example1.rb.txt +7 -7
  355. data/spec/parser/examples/extrafile.c.txt +8 -8
  356. data/spec/parser/examples/file.c.txt +28 -0
  357. data/spec/parser/examples/multifile.c.txt +22 -22
  358. data/spec/parser/examples/namespace.cpp.txt +68 -68
  359. data/spec/parser/examples/override.c.txt +424 -424
  360. data/spec/parser/examples/parse_in_order_001.rb.txt +2 -2
  361. data/spec/parser/examples/parse_in_order_002.rb.txt +1 -1
  362. data/spec/parser/examples/tag_handler_001.rb.txt +7 -7
  363. data/spec/parser/ruby/ast_node_spec.rb +33 -33
  364. data/spec/parser/ruby/legacy/statement_list_spec.rb +299 -299
  365. data/spec/parser/ruby/legacy/token_list_spec.rb +79 -79
  366. data/spec/parser/ruby/ruby_parser_spec.rb +508 -508
  367. data/spec/parser/ruby/token_resolver_spec.rb +165 -165
  368. data/spec/parser/source_parser_spec.rb +727 -727
  369. data/spec/parser/tag_parsing_spec.rb +17 -17
  370. data/spec/rake/yardoc_task_spec.rb +118 -118
  371. data/spec/registry_spec.rb +463 -463
  372. data/spec/registry_store_spec.rb +316 -316
  373. data/spec/rubygems/doc_manager_spec.rb +112 -112
  374. data/spec/serializers/data/serialized_yardoc/checksums +1 -1
  375. data/spec/serializers/file_system_serializer_spec.rb +145 -145
  376. data/spec/serializers/spec_helper.rb +2 -2
  377. data/spec/serializers/yardoc_serializer_spec.rb +78 -78
  378. data/spec/server/adapter_spec.rb +39 -39
  379. data/spec/server/commands/base_spec.rb +91 -91
  380. data/spec/server/commands/library_command_spec.rb +39 -39
  381. data/spec/server/doc_server_helper_spec.rb +72 -72
  382. data/spec/server/doc_server_serializer_spec.rb +60 -60
  383. data/spec/server/rack_adapter_spec.rb +21 -21
  384. data/spec/server/router_spec.rb +123 -123
  385. data/spec/server/spec_helper.rb +22 -22
  386. data/spec/server/static_caching_spec.rb +47 -47
  387. data/spec/server/webrick_servlet_spec.rb +20 -20
  388. data/spec/server_spec.rb +19 -19
  389. data/spec/spec_helper.rb +212 -212
  390. data/spec/tags/default_factory_spec.rb +168 -168
  391. data/spec/tags/default_tag_spec.rb +11 -11
  392. data/spec/tags/directives_spec.rb +463 -463
  393. data/spec/tags/library_spec.rb +48 -48
  394. data/spec/tags/overload_tag_spec.rb +53 -53
  395. data/spec/tags/ref_tag_list_spec.rb +53 -53
  396. data/spec/tags/types_explainer_spec.rb +203 -203
  397. data/spec/templates/class_spec.rb +45 -45
  398. data/spec/templates/constant_spec.rb +41 -41
  399. data/spec/templates/engine_spec.rb +131 -131
  400. data/spec/templates/examples/class001.html +308 -308
  401. data/spec/templates/examples/class001.txt +36 -36
  402. data/spec/templates/examples/class002.html +39 -39
  403. data/spec/templates/examples/constant001.txt +24 -24
  404. data/spec/templates/examples/constant002.txt +6 -6
  405. data/spec/templates/examples/constant003.txt +10 -10
  406. data/spec/templates/examples/method001.html +137 -137
  407. data/spec/templates/examples/method001.txt +35 -35
  408. data/spec/templates/examples/method002.html +91 -91
  409. data/spec/templates/examples/method002.txt +20 -20
  410. data/spec/templates/examples/method003.html +165 -165
  411. data/spec/templates/examples/method003.txt +45 -45
  412. data/spec/templates/examples/method004.html +48 -48
  413. data/spec/templates/examples/method004.txt +10 -10
  414. data/spec/templates/examples/method005.html +105 -105
  415. data/spec/templates/examples/method005.txt +33 -33
  416. data/spec/templates/examples/method006.html +107 -107
  417. data/spec/templates/examples/method006.txt +20 -20
  418. data/spec/templates/examples/module001.dot +33 -33
  419. data/spec/templates/examples/module001.html +833 -833
  420. data/spec/templates/examples/module001.txt +33 -33
  421. data/spec/templates/examples/module002.html +341 -341
  422. data/spec/templates/examples/module003.html +202 -202
  423. data/spec/templates/examples/module004.html +394 -394
  424. data/spec/templates/examples/module005.html +81 -81
  425. data/spec/templates/examples/tag001.txt +82 -82
  426. data/spec/templates/helpers/base_helper_spec.rb +171 -171
  427. data/spec/templates/helpers/html_helper_spec.rb +668 -653
  428. data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +65 -65
  429. data/spec/templates/helpers/markup/rdoc_markup_spec.rb +84 -84
  430. data/spec/templates/helpers/markup_helper_spec.rb +136 -136
  431. data/spec/templates/helpers/method_helper_spec.rb +107 -107
  432. data/spec/templates/helpers/module_helper_spec.rb +35 -35
  433. data/spec/templates/helpers/shared_signature_examples.rb +126 -126
  434. data/spec/templates/helpers/text_helper_spec.rb +65 -65
  435. data/spec/templates/method_spec.rb +118 -118
  436. data/spec/templates/module_spec.rb +203 -203
  437. data/spec/templates/onefile_spec.rb +66 -66
  438. data/spec/templates/section_spec.rb +144 -144
  439. data/spec/templates/spec_helper.rb +76 -76
  440. data/spec/templates/tag_spec.rb +52 -52
  441. data/spec/templates/template_spec.rb +410 -410
  442. data/spec/verifier_spec.rb +106 -106
  443. data/templates/default/class/dot/setup.rb +7 -7
  444. data/templates/default/class/dot/superklass.erb +2 -2
  445. data/templates/default/class/html/constructor_details.erb +8 -8
  446. data/templates/default/class/html/setup.rb +2 -2
  447. data/templates/default/class/html/subclasses.erb +4 -4
  448. data/templates/default/class/setup.rb +36 -36
  449. data/templates/default/class/text/setup.rb +12 -12
  450. data/templates/default/class/text/subclasses.erb +5 -5
  451. data/templates/default/constant/text/header.erb +11 -11
  452. data/templates/default/constant/text/setup.rb +4 -4
  453. data/templates/default/docstring/html/abstract.erb +4 -4
  454. data/templates/default/docstring/html/deprecated.erb +1 -1
  455. data/templates/default/docstring/html/index.erb +5 -5
  456. data/templates/default/docstring/html/note.erb +6 -6
  457. data/templates/default/docstring/html/private.erb +4 -4
  458. data/templates/default/docstring/html/text.erb +1 -1
  459. data/templates/default/docstring/html/todo.erb +6 -6
  460. data/templates/default/docstring/setup.rb +52 -52
  461. data/templates/default/docstring/text/abstract.erb +2 -2
  462. data/templates/default/docstring/text/deprecated.erb +2 -2
  463. data/templates/default/docstring/text/index.erb +2 -2
  464. data/templates/default/docstring/text/note.erb +3 -3
  465. data/templates/default/docstring/text/private.erb +2 -2
  466. data/templates/default/docstring/text/text.erb +1 -1
  467. data/templates/default/docstring/text/todo.erb +3 -3
  468. data/templates/default/fulldoc/html/css/full_list.css +58 -58
  469. data/templates/default/fulldoc/html/css/style.css +496 -496
  470. data/templates/default/fulldoc/html/frames.erb +17 -17
  471. data/templates/default/fulldoc/html/full_list.erb +37 -37
  472. data/templates/default/fulldoc/html/full_list_class.erb +2 -2
  473. data/templates/default/fulldoc/html/full_list_file.erb +7 -7
  474. data/templates/default/fulldoc/html/full_list_method.erb +10 -10
  475. data/templates/default/fulldoc/html/js/app.js +292 -292
  476. data/templates/default/fulldoc/html/js/full_list.js +216 -216
  477. data/templates/default/fulldoc/html/js/jquery.js +3 -3
  478. data/templates/default/fulldoc/html/setup.rb +241 -241
  479. data/templates/default/layout/dot/header.erb +5 -5
  480. data/templates/default/layout/dot/setup.rb +15 -15
  481. data/templates/default/layout/html/breadcrumb.erb +11 -11
  482. data/templates/default/layout/html/files.erb +11 -11
  483. data/templates/default/layout/html/footer.erb +5 -5
  484. data/templates/default/layout/html/headers.erb +15 -15
  485. data/templates/default/layout/html/index.erb +2 -2
  486. data/templates/default/layout/html/layout.erb +23 -23
  487. data/templates/default/layout/html/listing.erb +4 -4
  488. data/templates/default/layout/html/objects.erb +32 -32
  489. data/templates/default/layout/html/script_setup.erb +4 -4
  490. data/templates/default/layout/html/search.erb +12 -12
  491. data/templates/default/layout/html/setup.rb +89 -89
  492. data/templates/default/method/html/header.erb +16 -16
  493. data/templates/default/method/setup.rb +4 -4
  494. data/templates/default/method_details/html/header.erb +2 -2
  495. data/templates/default/method_details/html/method_signature.erb +24 -24
  496. data/templates/default/method_details/html/source.erb +9 -9
  497. data/templates/default/method_details/setup.rb +11 -11
  498. data/templates/default/method_details/text/header.erb +10 -10
  499. data/templates/default/method_details/text/method_signature.erb +12 -12
  500. data/templates/default/method_details/text/setup.rb +11 -11
  501. data/templates/default/module/dot/child.erb +1 -1
  502. data/templates/default/module/dot/dependencies.erb +2 -2
  503. data/templates/default/module/dot/header.erb +6 -6
  504. data/templates/default/module/dot/info.erb +13 -13
  505. data/templates/default/module/dot/setup.rb +15 -15
  506. data/templates/default/module/html/attribute_details.erb +10 -10
  507. data/templates/default/module/html/attribute_summary.erb +8 -8
  508. data/templates/default/module/html/box_info.erb +43 -43
  509. data/templates/default/module/html/children.erb +8 -8
  510. data/templates/default/module/html/constant_summary.erb +17 -17
  511. data/templates/default/module/html/defines.erb +2 -2
  512. data/templates/default/module/html/header.erb +5 -5
  513. data/templates/default/module/html/inherited_attributes.erb +14 -14
  514. data/templates/default/module/html/inherited_constants.erb +8 -8
  515. data/templates/default/module/html/inherited_methods.erb +18 -18
  516. data/templates/default/module/html/item_summary.erb +40 -40
  517. data/templates/default/module/html/method_details_list.erb +9 -9
  518. data/templates/default/module/html/method_summary.erb +13 -13
  519. data/templates/default/module/html/methodmissing.erb +12 -12
  520. data/templates/default/module/setup.rb +167 -167
  521. data/templates/default/module/text/children.erb +9 -9
  522. data/templates/default/module/text/class_meths_list.erb +7 -7
  523. data/templates/default/module/text/extends.erb +7 -7
  524. data/templates/default/module/text/header.erb +7 -7
  525. data/templates/default/module/text/includes.erb +7 -7
  526. data/templates/default/module/text/instance_meths_list.erb +7 -7
  527. data/templates/default/module/text/setup.rb +13 -13
  528. data/templates/default/onefile/html/files.erb +4 -4
  529. data/templates/default/onefile/html/headers.erb +6 -6
  530. data/templates/default/onefile/html/layout.erb +17 -17
  531. data/templates/default/onefile/html/readme.erb +2 -2
  532. data/templates/default/onefile/html/setup.rb +62 -62
  533. data/templates/default/root/dot/child.erb +2 -2
  534. data/templates/default/root/dot/setup.rb +6 -6
  535. data/templates/default/root/html/setup.rb +2 -2
  536. data/templates/default/tags/html/example.erb +10 -10
  537. data/templates/default/tags/html/index.erb +2 -2
  538. data/templates/default/tags/html/option.erb +24 -24
  539. data/templates/default/tags/html/overload.erb +13 -13
  540. data/templates/default/tags/html/see.erb +7 -7
  541. data/templates/default/tags/html/tag.erb +20 -20
  542. data/templates/default/tags/setup.rb +57 -57
  543. data/templates/default/tags/text/example.erb +12 -12
  544. data/templates/default/tags/text/index.erb +1 -1
  545. data/templates/default/tags/text/option.erb +20 -20
  546. data/templates/default/tags/text/overload.erb +19 -19
  547. data/templates/default/tags/text/see.erb +11 -11
  548. data/templates/default/tags/text/tag.erb +13 -13
  549. data/templates/guide/class/html/setup.rb +2 -2
  550. data/templates/guide/docstring/html/setup.rb +2 -2
  551. data/templates/guide/fulldoc/html/css/style.css +108 -108
  552. data/templates/guide/fulldoc/html/js/app.js +33 -33
  553. data/templates/guide/fulldoc/html/setup.rb +74 -74
  554. data/templates/guide/layout/html/layout.erb +81 -81
  555. data/templates/guide/layout/html/setup.rb +25 -25
  556. data/templates/guide/method/html/header.erb +17 -17
  557. data/templates/guide/method/html/setup.rb +22 -22
  558. data/templates/guide/module/html/header.erb +6 -6
  559. data/templates/guide/module/html/method_list.erb +4 -4
  560. data/templates/guide/module/html/setup.rb +27 -27
  561. data/templates/guide/onefile/html/files.erb +4 -4
  562. data/templates/guide/onefile/html/setup.rb +6 -6
  563. data/templates/guide/onefile/html/toc.erb +3 -3
  564. data/templates/guide/tags/html/setup.rb +9 -9
  565. data/yard.gemspec +43 -43
  566. metadata +4 -4
@@ -1,165 +1,165 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe YARD::Parser::Ruby::TokenResolver do
4
- before(:all) do
5
- YARD.parse_string <<-eof
6
- module A
7
- def nomatch; end
8
-
9
- module B
10
- class C
11
- def initialize; end
12
-
13
- # @return [A::B::C]
14
- def self.foo; end
15
-
16
- # @return [self]
17
- def self.foo2; end
18
-
19
- def bar; end
20
-
21
- # @return [nil, D<String>]
22
- def baz; end
23
-
24
- # @return [nil]
25
- # @return [D<String>]
26
- def baz2; end
27
-
28
- # @overload qux(a)
29
- # @return [nil]
30
- # @overload qux(b)
31
- # @return [D<String>]
32
- def qux; end
33
- end
34
-
35
- class SubC < C
36
- end
37
- end
38
- end
39
-
40
- module D
41
- def baz; end
42
- end
43
-
44
- class Q
45
- def method; end
46
-
47
- # @return [Q]
48
- def self.q; end
49
- end
50
- eof
51
- end
52
-
53
- def tokens_match
54
- expect(@resolved.map {|t| t.first.last }.join).to eq @src
55
- end
56
-
57
- def objs_match(*objects)
58
- other_objs = @resolved.reject {|_, o| !o }.map {|_, o| o.path }
59
- expect(other_objs).to eq objects.flatten
60
- tokens_match
61
- end
62
-
63
- def tokenize(src, object = nil)
64
- @src = src
65
- @resolver = YARD::Parser::Ruby::TokenResolver.new(src, object)
66
- @resolved = @resolver.map {|t, o| [t[0, 2], o] }
67
- end
68
-
69
- it "returns regular tokens" do
70
- str = "def foo; Z::X::Y end"
71
- tokenize(str)
72
- tokens_match
73
- end
74
-
75
- it "resolves objects in compound constant paths" do
76
- tokenize "A::B::C"
77
- objs_match "A", "A::B", "A::B::C"
78
- end
79
-
80
- it "ignores full constant path if it breaks at beginning" do
81
- tokenize "E::A::B::C"
82
- objs_match []
83
- end
84
-
85
- it "ignores rest of constant path if sub-objects don't match" do
86
- tokenize "D::A::B::C"
87
- objs_match "D"
88
- end
89
-
90
- it "resets parsing at non-op tokens" do
91
- tokenize "A::B::C < Q"
92
- objs_match "A", "A::B", "A::B::C", "Q"
93
- end
94
-
95
- it "does not restart constant path" do
96
- tokenize "A::B::D::A"
97
- objs_match "A", "A::B"
98
- end
99
-
100
- it "resolves objects from base namespace" do
101
- tokenize "A::B::C C", Registry.at("A::B")
102
- objs_match "A", "A::B", "A::B::C", "A::B::C"
103
- end
104
-
105
- it "resolves methods" do
106
- tokenize "A::B::C.foo"
107
- objs_match "A", "A::B", "A::B::C", "A::B::C.foo"
108
- end
109
-
110
- it "supports 'new' constructor method" do
111
- tokenize "A::B::C.new"
112
- objs_match "A", "A::B", "A::B::C", "A::B::C#initialize"
113
- end
114
-
115
- it "skips constructor method if not found but continues resolving" do
116
- tokenize "Q.new.method"
117
- objs_match "Q", "Q#method"
118
- end
119
-
120
- it "resolves methods in inheritance tree" do
121
- tokenize "A::B::SubC.new"
122
- objs_match "A", "A::B", "A::B::SubC", "A::B::C#initialize"
123
- end
124
-
125
- it "parses compound method call chains based on return type" do
126
- tokenize "A::B::C.foo.baz"
127
- objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz"
128
- end
129
-
130
- it "stops resolving if return types not found" do
131
- tokenize "A::B::C.foo.bar.baz.baz"
132
- objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#bar"
133
- end
134
-
135
- it "handles multiple return types (returns first valid type match)" do
136
- tokenize "A::B::C.foo.baz.baz"
137
- objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz", "D#baz"
138
- end
139
-
140
- it "doesn't perform lexical matching on methods" do
141
- tokenize "A::B::C.nomatch"
142
- objs_match "A", "A::B", "A::B::C"
143
- end
144
-
145
- it "handles multiple return tags (returns first valid type match)" do
146
- tokenize "A::B::C.foo.baz2.baz"
147
- objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz2", "D#baz"
148
- end
149
-
150
- it "handles self as return type" do
151
- tokenize "A::B::C.foo2.baz"
152
- objs_match "A", "A::B", "A::B::C", "A::B::C.foo2", "A::B::C#baz"
153
- end
154
-
155
- it "handles multiple return tags inside overload tags" do
156
- tokenize "A::B::C.foo.qux.baz"
157
- objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#qux", "D#baz"
158
- end
159
-
160
- it "resolves method calls with arguments" do
161
- tokenize "Q.q(A::B, A::B::C.foo().bar).q.q"
162
- objs_match "Q", "Q.q", "A", "A::B", "A", "A::B", "A::B::C",
163
- "A::B::C.foo", "A::B::C#bar", "Q.q", "Q.q"
164
- end
165
- end if HAVE_RIPPER
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe YARD::Parser::Ruby::TokenResolver do
4
+ before(:all) do
5
+ YARD.parse_string <<-eof
6
+ module A
7
+ def nomatch; end
8
+
9
+ module B
10
+ class C
11
+ def initialize; end
12
+
13
+ # @return [A::B::C]
14
+ def self.foo; end
15
+
16
+ # @return [self]
17
+ def self.foo2; end
18
+
19
+ def bar; end
20
+
21
+ # @return [nil, D<String>]
22
+ def baz; end
23
+
24
+ # @return [nil]
25
+ # @return [D<String>]
26
+ def baz2; end
27
+
28
+ # @overload qux(a)
29
+ # @return [nil]
30
+ # @overload qux(b)
31
+ # @return [D<String>]
32
+ def qux; end
33
+ end
34
+
35
+ class SubC < C
36
+ end
37
+ end
38
+ end
39
+
40
+ module D
41
+ def baz; end
42
+ end
43
+
44
+ class Q
45
+ def method; end
46
+
47
+ # @return [Q]
48
+ def self.q; end
49
+ end
50
+ eof
51
+ end
52
+
53
+ def tokens_match
54
+ expect(@resolved.map {|t| t.first.last }.join).to eq @src
55
+ end
56
+
57
+ def objs_match(*objects)
58
+ other_objs = @resolved.reject {|_, o| !o }.map {|_, o| o.path }
59
+ expect(other_objs).to eq objects.flatten
60
+ tokens_match
61
+ end
62
+
63
+ def tokenize(src, object = nil)
64
+ @src = src
65
+ @resolver = YARD::Parser::Ruby::TokenResolver.new(src, object)
66
+ @resolved = @resolver.map {|t, o| [t[0, 2], o] }
67
+ end
68
+
69
+ it "returns regular tokens" do
70
+ str = "def foo; Z::X::Y end"
71
+ tokenize(str)
72
+ tokens_match
73
+ end
74
+
75
+ it "resolves objects in compound constant paths" do
76
+ tokenize "A::B::C"
77
+ objs_match "A", "A::B", "A::B::C"
78
+ end
79
+
80
+ it "ignores full constant path if it breaks at beginning" do
81
+ tokenize "E::A::B::C"
82
+ objs_match []
83
+ end
84
+
85
+ it "ignores rest of constant path if sub-objects don't match" do
86
+ tokenize "D::A::B::C"
87
+ objs_match "D"
88
+ end
89
+
90
+ it "resets parsing at non-op tokens" do
91
+ tokenize "A::B::C < Q"
92
+ objs_match "A", "A::B", "A::B::C", "Q"
93
+ end
94
+
95
+ it "does not restart constant path" do
96
+ tokenize "A::B::D::A"
97
+ objs_match "A", "A::B"
98
+ end
99
+
100
+ it "resolves objects from base namespace" do
101
+ tokenize "A::B::C C", Registry.at("A::B")
102
+ objs_match "A", "A::B", "A::B::C", "A::B::C"
103
+ end
104
+
105
+ it "resolves methods" do
106
+ tokenize "A::B::C.foo"
107
+ objs_match "A", "A::B", "A::B::C", "A::B::C.foo"
108
+ end
109
+
110
+ it "supports 'new' constructor method" do
111
+ tokenize "A::B::C.new"
112
+ objs_match "A", "A::B", "A::B::C", "A::B::C#initialize"
113
+ end
114
+
115
+ it "skips constructor method if not found but continues resolving" do
116
+ tokenize "Q.new.method"
117
+ objs_match "Q", "Q#method"
118
+ end
119
+
120
+ it "resolves methods in inheritance tree" do
121
+ tokenize "A::B::SubC.new"
122
+ objs_match "A", "A::B", "A::B::SubC", "A::B::C#initialize"
123
+ end
124
+
125
+ it "parses compound method call chains based on return type" do
126
+ tokenize "A::B::C.foo.baz"
127
+ objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz"
128
+ end
129
+
130
+ it "stops resolving if return types not found" do
131
+ tokenize "A::B::C.foo.bar.baz.baz"
132
+ objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#bar"
133
+ end
134
+
135
+ it "handles multiple return types (returns first valid type match)" do
136
+ tokenize "A::B::C.foo.baz.baz"
137
+ objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz", "D#baz"
138
+ end
139
+
140
+ it "doesn't perform lexical matching on methods" do
141
+ tokenize "A::B::C.nomatch"
142
+ objs_match "A", "A::B", "A::B::C"
143
+ end
144
+
145
+ it "handles multiple return tags (returns first valid type match)" do
146
+ tokenize "A::B::C.foo.baz2.baz"
147
+ objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#baz2", "D#baz"
148
+ end
149
+
150
+ it "handles self as return type" do
151
+ tokenize "A::B::C.foo2.baz"
152
+ objs_match "A", "A::B", "A::B::C", "A::B::C.foo2", "A::B::C#baz"
153
+ end
154
+
155
+ it "handles multiple return tags inside overload tags" do
156
+ tokenize "A::B::C.foo.qux.baz"
157
+ objs_match "A", "A::B", "A::B::C", "A::B::C.foo", "A::B::C#qux", "D#baz"
158
+ end
159
+
160
+ it "resolves method calls with arguments" do
161
+ tokenize "Q.q(A::B, A::B::C.foo().bar).q.q"
162
+ objs_match "Q", "Q.q", "A", "A::B", "A", "A::B", "A::B::C",
163
+ "A::B::C.foo", "A::B::C#bar", "Q.q", "Q.q"
164
+ end
165
+ end if HAVE_RIPPER
@@ -1,727 +1,727 @@
1
- # frozen_string_literal: true
2
-
3
- class MyParser < Parser::Base; end
4
-
5
- RSpec.shared_examples_for "parser type registration" do
6
- after do
7
- Parser::SourceParser.parser_types.delete(:my_parser)
8
- Parser::SourceParser.parser_type_extensions.delete(:my_parser)
9
- end
10
- end
11
-
12
- RSpec.describe YARD::Parser::SourceParser do
13
- before do
14
- Registry.clear
15
- end
16
-
17
- def parse_list(*list)
18
- files = list.map do |v|
19
- filename, source = *v
20
- allow(File).to receive(:read_binary).with(filename).and_return(source)
21
- filename
22
- end
23
- Parser::SourceParser.send(:parse_in_order, *files)
24
- end
25
-
26
- def before_list(&block)
27
- Parser::SourceParser.before_parse_list(&block)
28
- end
29
-
30
- def after_list(&block)
31
- Parser::SourceParser.after_parse_list(&block)
32
- end
33
-
34
- def before_file(&block)
35
- Parser::SourceParser.before_parse_file(&block)
36
- end
37
-
38
- def after_file(&block)
39
- Parser::SourceParser.after_parse_file(&block)
40
- end
41
-
42
- describe ".before_parse_list" do
43
- before do
44
- Parser::SourceParser.before_parse_list_callbacks.clear
45
- Parser::SourceParser.after_parse_list_callbacks.clear
46
- end
47
-
48
- it "handles basic callback support" do
49
- before_list do |files, globals|
50
- expect(files).to eq ['foo.rb', 'bar.rb']
51
- expect(globals).to eq OpenStruct.new
52
- end
53
- parse_list ['foo.rb', 'foo!'], ['bar.rb', 'class Foo; end']
54
- expect(Registry.at('Foo')).not_to be nil
55
- end
56
-
57
- it "supports multiple callbacks" do
58
- checks = []
59
- before_list { checks << :one }
60
- before_list { checks << :two }
61
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
62
- expect(Registry.at('Foo')).not_to be nil
63
- expect(checks).to eq [:one, :two]
64
- end
65
-
66
- it "cancels parsing if it returns false" do
67
- checks = []
68
- before_list { checks << :one }
69
- before_list { false }
70
- before_list { checks << :three }
71
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
72
- expect(Registry.at('Foo')).to be nil
73
- expect(checks).to eq [:one]
74
- end
75
-
76
- it "does not cancel on nil" do
77
- checks = []
78
- before_list { checks << :one }
79
- before_list { nil }
80
- before_list { checks << :two }
81
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
82
- expect(Registry.at('Foo')).not_to be nil
83
- expect(checks).to eq [:one, :two]
84
- end
85
-
86
- it "passes in globals" do
87
- before_list {|_f, g| g.x = 1 }
88
- before_list {|_f, g| g.x += 1 }
89
- before_list {|_f, g| g.x += 1 }
90
- after_list {|_f, g| expect(g.x).to eq 3 }
91
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
92
- expect(Registry.at('Foo')).not_to be nil
93
- end
94
- end
95
-
96
- describe ".after_parse_list" do
97
- before do
98
- Parser::SourceParser.before_parse_list_callbacks.clear
99
- Parser::SourceParser.after_parse_list_callbacks.clear
100
- end
101
-
102
- it "handles basic callback support and maintain files/globals" do
103
- before_list {|_f, g| g.foo = :bar }
104
- after_list do |files, globals|
105
- expect(files).to eq ['foo.rb', 'bar.rb']
106
- expect(globals.foo).to eq :bar
107
- end
108
- parse_list ['foo.rb', 'foo!'], ['bar.rb', 'class Foo; end']
109
- expect(Registry.at('Foo')).not_to be nil
110
- end
111
-
112
- it "supports multiple callbacks" do
113
- checks = []
114
- after_list { checks << :one }
115
- after_list { checks << :two }
116
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
117
- expect(Registry.at('Foo')).not_to be nil
118
- expect(checks).to eq [:one, :two]
119
- end
120
-
121
- it "does not cancel parsing if it returns false" do
122
- checks = []
123
- after_list { checks << :one }
124
- after_list { false }
125
- after_list { checks << :three }
126
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
127
- expect(Registry.at('Foo')).not_to be nil
128
- expect(checks).to eq [:one, :three]
129
- end
130
- end
131
-
132
- describe ".before_parse_file" do
133
- before do
134
- Parser::SourceParser.before_parse_file_callbacks.clear
135
- Parser::SourceParser.after_parse_file_callbacks.clear
136
- end
137
-
138
- it "handles basic callback support" do
139
- before_file do |parser|
140
- expect(parser.contents).to eq 'class Foo; end'
141
- expect(parser.file).to match(/(foo|bar)\.rb/)
142
- end
143
- parse_list ['foo.rb', 'class Foo; end'], ['bar.rb', 'class Foo; end']
144
- expect(Registry.at('Foo')).not_to be nil
145
- end
146
-
147
- it "supports multiple callbacks" do
148
- checks = []
149
- before_file { checks << :one }
150
- before_file { checks << :two }
151
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
152
- expect(Registry.at('Foo')).not_to be nil
153
- expect(checks).to eq [:one, :two, :one, :two, :one, :two]
154
- end
155
-
156
- it "cancels parsing if it returns false" do
157
- checks = []
158
- before_file { checks << :one }
159
- before_file { false }
160
- before_file { checks << :three }
161
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
162
- expect(Registry.at('Foo')).to be nil
163
- expect(checks).to eq [:one, :one, :one]
164
- end
165
-
166
- it "does not cancel on nil" do
167
- checks = []
168
- before_file { checks << :one }
169
- before_file { nil }
170
- before_file { checks << :two }
171
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
172
- expect(Registry.at('Foo')).not_to be nil
173
- expect(checks).to eq [:one, :two, :one, :two, :one, :two]
174
- end
175
- end
176
-
177
- describe ".after_parse_file" do
178
- before do
179
- Parser::SourceParser.before_parse_file_callbacks.clear
180
- Parser::SourceParser.after_parse_file_callbacks.clear
181
- end
182
-
183
- it "handles basic callback support" do
184
- after_file do |parser|
185
- expect(parser.contents).to eq 'class Foo; end'
186
- expect(parser.file).to match(/(foo|bar)\.rb/)
187
- end
188
- parse_list ['foo.rb', 'class Foo; end'], ['bar.rb', 'class Foo; end']
189
- expect(Registry.at('Foo')).not_to be nil
190
- end
191
-
192
- it "supports multiple callbacks" do
193
- checks = []
194
- after_file { checks << :one }
195
- after_file { checks << :two }
196
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
197
- expect(Registry.at('Foo')).not_to be nil
198
- expect(checks).to eq [:one, :two, :one, :two, :one, :two]
199
- end
200
-
201
- it "does not cancel parsing if it returns false" do
202
- checks = []
203
- after_file { checks << :one }
204
- after_file { false }
205
- after_file { checks << :three }
206
- parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
207
- expect(Registry.at('Foo')).not_to be nil
208
- expect(checks).to eq [:one, :three, :one, :three, :one, :three]
209
- end
210
- end
211
-
212
- describe ".register_parser_type" do
213
- it_should_behave_like "parser type registration"
214
-
215
- it "registers a subclass of Parser::Base" do
216
- parser = double(:parser)
217
- expect(parser).to receive(:parse)
218
- expect(MyParser).to receive(:new).with('content', '(stdin)').and_return(parser)
219
- Parser::SourceParser.register_parser_type(:my_parser, MyParser, 'myparser')
220
- Parser::SourceParser.parse_string('content', :my_parser)
221
- end
222
-
223
- it "requires class to be a subclass of Parser::Base" do
224
- expect { Parser::SourceParser.register_parser_type(:my_parser, String) }.to raise_error(ArgumentError)
225
- expect { Parser::SourceParser.register_parser_type(:my_parser, Parser::Base) }.to raise_error(ArgumentError)
226
- end
227
- end
228
-
229
- describe ".parser_type_for_extension" do
230
- it_should_behave_like "parser type registration"
231
-
232
- it "finds an extension in a registered array of extensions" do
233
- Parser::SourceParser.register_parser_type(:my_parser, MyParser, ['a', 'b', 'd'])
234
- expect(Parser::SourceParser.parser_type_for_extension('a')).to eq :my_parser
235
- expect(Parser::SourceParser.parser_type_for_extension('b')).to eq :my_parser
236
- expect(Parser::SourceParser.parser_type_for_extension('d')).to eq :my_parser
237
- expect(Parser::SourceParser.parser_type_for_extension('c')).not_to eq :my_parser
238
- end
239
-
240
- it "finds an extension in a Regexp" do
241
- Parser::SourceParser.register_parser_type(:my_parser, MyParser, /abc$/)
242
- expect(Parser::SourceParser.parser_type_for_extension('dabc')).to eq :my_parser
243
- expect(Parser::SourceParser.parser_type_for_extension('dabcd')).not_to eq :my_parser
244
- end
245
-
246
- it "finds an extension in a list of Regexps" do
247
- Parser::SourceParser.register_parser_type(:my_parser, MyParser, [/ab$/, /abc$/])
248
- expect(Parser::SourceParser.parser_type_for_extension('dabc')).to eq :my_parser
249
- expect(Parser::SourceParser.parser_type_for_extension('dabcd')).not_to eq :my_parser
250
- end
251
-
252
- it "finds an extension in a String" do
253
- Parser::SourceParser.register_parser_type(:my_parser, MyParser, "abc")
254
- expect(Parser::SourceParser.parser_type_for_extension('abc')).to eq :my_parser
255
- expect(Parser::SourceParser.parser_type_for_extension('abcd')).not_to eq :my_parser
256
- end
257
- end
258
-
259
- describe "#parse_string" do
260
- it "parses basic Ruby code" do
261
- YARD.parse_string(<<-eof)
262
- module Hello
263
- class Hi
264
- # Docstring
265
- # Docstring2
266
- def me; "VALUE" end
267
- end
268
- end
269
- eof
270
- expect(Registry.at(:Hello)).not_to eq nil
271
- expect(Registry.at("Hello::Hi#me")).not_to eq nil
272
- expect(Registry.at("Hello::Hi#me").docstring).to eq "Docstring\nDocstring2"
273
- expect(Registry.at("Hello::Hi#me").docstring.line_range).to eq(3..4)
274
- end
275
-
276
- it "parses Ruby code with metaclasses" do
277
- YARD.parse_string(<<-eof)
278
- module Hello
279
- class Hi
280
- class <<self
281
- # Docstring
282
- def me; "VALUE" end
283
- end
284
- end
285
- end
286
- eof
287
- expect(Registry.at(:Hello)).not_to eq nil
288
- expect(Registry.at("Hello::Hi.me")).not_to eq nil
289
- expect(Registry.at("Hello::Hi.me").docstring).to eq "Docstring"
290
- end
291
-
292
- it "only uses prepended comments for an object" do
293
- YARD.parse_string(<<-eof)
294
- # Test
295
-
296
- # PASS
297
- module Hello
298
- end # FAIL
299
- eof
300
- expect(Registry.at(:Hello).docstring).to eq "PASS"
301
- end
302
-
303
- it "does not add comments appended to last line of block" do
304
- YARD.parse_string <<-eof
305
- module Hello2
306
- end # FAIL
307
- eof
308
- expect(Registry.at(:Hello2).docstring).to be_blank
309
- end
310
-
311
- it "adds comments appended to an object's first line" do
312
- YARD.parse_string <<-eof
313
- module Hello # PASS
314
- HELLO
315
- end
316
-
317
- module Hello2 # PASS
318
- # ANOTHER PASS
319
- def x; end
320
- end
321
- eof
322
-
323
- expect(Registry.at(:Hello).docstring).to eq "PASS"
324
- expect(Registry.at(:Hello2).docstring).to eq "PASS"
325
- expect(Registry.at('Hello2#x').docstring).to eq "ANOTHER PASS"
326
- end
327
-
328
- it "takes preceding comments only if they exist" do
329
- YARD.parse_string <<-eof
330
- # PASS
331
- module Hello # FAIL
332
- HELLO
333
- end
334
- eof
335
-
336
- expect(Registry.at(:Hello).docstring).to eq "PASS"
337
- end
338
-
339
- it "strips all hashes prefixed on comment line" do
340
- YARD.parse_string(<<-eof)
341
- ### PASS
342
- #### PASS
343
- ##### PASS
344
- module Hello
345
- end
346
- eof
347
- expect(Registry.at(:Hello).docstring).to eq "PASS\nPASS\nPASS"
348
- end
349
-
350
- it "handles =begin/=end style comments" do
351
- YARD.parse_string "=begin\nfoo\nbar\n=end\nclass Foo; end\n"
352
- expect(Registry.at(:Foo).docstring).to eq "foo\nbar"
353
-
354
- YARD.parse_string "=begin\n\nfoo\nbar\n=end\nclass Foo; end\n"
355
- expect(Registry.at(:Foo).docstring).to eq "foo\nbar"
356
-
357
- YARD.parse_string "=begin\nfoo\n\nbar\n=end\nclass Foo; end\n"
358
- expect(Registry.at(:Foo).docstring).to eq "foo\n\nbar"
359
- end
360
-
361
- it "knows about docstrings starting with ##" do
362
- {'#' => false, '##' => true}.each do |hash, expected|
363
- YARD.parse_string "#{hash}\n# Foo bar\nclass Foo; end"
364
- expect(Registry.at(:Foo).docstring.hash_flag).to eq expected
365
- end
366
- end
367
-
368
- it "removes shebang from initial file comments" do
369
- YARD.parse_string "#!/bin/ruby\n# this is a comment\nclass Foo; end"
370
- expect(Registry.at(:Foo).docstring).to eq "this is a comment"
371
- end
372
-
373
- it "removes encoding line from initial file comments" do
374
- YARD.parse_string "# encoding: utf-8\n# this is a comment\nclass Foo; end"
375
- expect(Registry.at(:Foo).docstring).to eq "this is a comment"
376
- end
377
-
378
- it "adds macros on any object" do
379
- YARD.parse_string <<-eof
380
- # @!macro [new] foo
381
- # This is a macro
382
- # @return [String] the string
383
- class Foo
384
- # @!macro foo
385
- def foo; end
386
- end
387
- eof
388
-
389
- macro = CodeObjects::MacroObject.find('foo')
390
- expect(macro.macro_data).to eq "This is a macro\n@return [String] the string"
391
- expect(Registry.at('Foo').docstring.to_raw).to eq macro.macro_data
392
- expect(Registry.at('Foo#foo').docstring.to_raw).to eq macro.macro_data
393
- end
394
-
395
- it "allows directives parsed on lone comments" do
396
- YARD.parse_string(<<-eof)
397
- class Foo
398
- # @!method foo(a = "hello")
399
- # @!scope class
400
- # @!visibility private
401
- # @param [String] a the name of the foo
402
- # @return [Symbol] the symbolized foo
403
-
404
- # @!method bar(value)
405
- end
406
- eof
407
- foo = Registry.at('Foo.foo')
408
- bar = Registry.at('Foo#bar')
409
- expect(foo).not_to be nil
410
- expect(foo.visibility).to eq :private
411
- expect(foo.tag(:param).name).to eq 'a'
412
- expect(foo.tag(:return).types).to eq ['Symbol']
413
- expect(bar).not_to be nil
414
- expect(bar.signature).to eq 'def bar(value)'
415
- end
416
-
417
- it "parses lone comments at end of blocks" do
418
- YARD.parse_string(<<-eof)
419
- class Foo
420
- none
421
-
422
- # @!method foo(a = "hello")
423
- end
424
- eof
425
- foo = Registry.at('Foo#foo')
426
- expect(foo).not_to be nil
427
- expect(foo.signature).to eq 'def foo(a = "hello")'
428
- end
429
-
430
- it "handles lone comment with no code" do
431
- YARD.parse_string '# @!method foo(a = "hello")'
432
- foo = Registry.at('#foo')
433
- expect(foo).not_to be nil
434
- expect(foo.signature).to eq 'def foo(a = "hello")'
435
- end
436
-
437
- it "handles non-ASCII encoding in heredoc" do
438
- YARD.parse_string <<-eof
439
- # encoding: utf-8
440
-
441
- heredoc <<-ending
442
- foo\u{ffe2} bar.
443
- ending
444
-
445
- # Hello \u{ffe2} world
446
- class Foo < Bar
447
- attr_accessor :foo
448
- end
449
- eof
450
- expect(Registry.at('Foo').superclass).to eq P('Bar')
451
- end
452
- end
453
-
454
- describe "#parse" do
455
- it "parses a basic Ruby file" do
456
- parse_file :example1, __FILE__
457
- expect(Registry.at(:Hello)).not_to eq nil
458
- expect(Registry.at("Hello::Hi#me")).not_to eq nil
459
- expect(Registry.at("Hello::Hi#me").docstring).to eq "Docstring"
460
- end
461
-
462
- it "parses a set of file globs" do
463
- expect(Dir).to receive(:[]).with('lib/**/*.rb').and_return([])
464
- YARD.parse('lib/**/*.rb')
465
- end
466
-
467
- it "parses a set of absolute paths" do
468
- expect(Dir).not_to receive(:[])
469
- expect(File).to receive(:file?).with('/path/to/file').and_return(true)
470
- expect(File).to receive(:read_binary).with('/path/to/file').and_return("")
471
- YARD.parse('/path/to/file')
472
- end
473
-
474
- it "cleans paths before parsing" do
475
- expect(File).to receive(:open).and_return("")
476
- parser = Parser::SourceParser.new(:ruby, true)
477
- parser.parse('a//b//c')
478
- expect(parser.file).to eq 'a/b/c'
479
- end
480
-
481
- it "parses files with '*' in them as globs and others as absolute paths" do
482
- expect(Dir).to receive(:[]).with('*.rb').and_return(['a.rb', 'b.rb'])
483
- expect(File).to receive(:file?).with('/path/to/file').and_return(true)
484
- expect(File).to receive(:file?).with('a.rb').and_return(true)
485
- expect(File).to receive(:file?).with('b.rb').and_return(true)
486
- expect(File).to receive(:read_binary).with('/path/to/file').and_return("")
487
- expect(File).to receive(:read_binary).with('a.rb').and_return("")
488
- expect(File).to receive(:read_binary).with('b.rb').and_return("")
489
- YARD.parse ['/path/to/file', '*.rb']
490
- end
491
-
492
- it "converts directories into globs" do
493
- expect(Dir).to receive(:[]).with('foo/**/*.{rb,c,cc,cxx,cpp}').and_return(['foo/a.rb', 'foo/bar/b.rb'])
494
- expect(File).to receive(:directory?).with('foo').and_return(true)
495
- expect(File).to receive(:file?).with('foo/a.rb').and_return(true)
496
- expect(File).to receive(:file?).with('foo/bar/b.rb').and_return(true)
497
- expect(File).to receive(:read_binary).with('foo/a.rb').and_return("")
498
- expect(File).to receive(:read_binary).with('foo/bar/b.rb').and_return("")
499
- YARD.parse ['foo']
500
- end
501
-
502
- it "uses Registry.checksums cache if file is cached" do
503
- data = 'DATA'
504
- hash = Registry.checksum_for(data)
505
- cmock = double(:cmock)
506
- expect(cmock).to receive(:[]).with('foo/bar').and_return(hash)
507
- expect(Registry).to receive(:checksums).and_return(cmock)
508
- expect(File).to receive(:file?).with('foo/bar').and_return(true)
509
- expect(File).to receive(:read_binary).with('foo/bar').and_return(data)
510
- YARD.parse('foo/bar')
511
- end
512
-
513
- it "supports excluded paths" do
514
- expect(File).to receive(:file?).with('foo/bar').and_return(true)
515
- expect(File).to receive(:file?).with('foo/baz').and_return(true)
516
- expect(File).not_to receive(:read_binary)
517
- YARD.parse(["foo/bar", "foo/baz"], ["foo", /baz$/])
518
- end
519
-
520
- it "converts file contents to proper encoding if coding line is present" do
521
- valid = []
522
- valid << "# encoding: sjis"
523
- valid << "# encoding: utf-8"
524
- valid << "# xxxxxencoding: sjis"
525
- valid << "# xxxxxencoding: sjis xxxxxx"
526
- valid << "# ENCODING: sjis"
527
- valid << "#coDiNG: sjis"
528
- valid << "# -*- coding: sjis -*-"
529
- valid << "# -*- coding: utf-8; indent-tabs-mode: nil"
530
- valid << "### coding: sjis"
531
- valid << "# encoding=sjis"
532
- valid << "# encoding:sjis"
533
- valid << "# encoding = sjis"
534
- valid << "# encoding == sjis"
535
- valid << "# encoding : sjis"
536
- valid << "# encoding :: sjis"
537
- valid << "#!/bin/shebang\n# encoding: sjis"
538
- valid << "#!/bin/shebang\r\n# coding: sjis"
539
- invalid = []
540
- invalid << "#\n# encoding: sjis"
541
- invalid << "#!/bin/shebang\n#\n# encoding: sjis"
542
- invalid << "# !/bin/shebang\n# encoding: sjis"
543
- {:to => valid, :not_to => invalid}.each do |msg, list|
544
- list.each do |src|
545
- Registry.clear
546
- parser = Parser::SourceParser.new
547
- expect(File).to receive(:read_binary).with('tmpfile').and_return(src)
548
- result = parser.parse("tmpfile")
549
- if HAVE_RIPPER && YARD.ruby19?
550
- if msg == :not_to
551
- default_encoding = 'UTF-8'
552
- expect(result.enumerator[0].source.encoding.to_s).to eq(default_encoding)
553
- else
554
- expect(['Shift_JIS', 'Windows-31J', 'UTF-8']).send(msg,
555
- include(result.enumerator[0].source.encoding.to_s))
556
- end
557
- end
558
- expect(result.encoding_line).send(msg, eq(src.split("\n").last))
559
- end
560
- end
561
- end
562
-
563
- it "converts C file contents to proper encoding if coding line is present" do
564
- valid = []
565
- valid << "/* coding: utf-8 */"
566
- valid << "/* -*- coding: utf-8; c-file-style: \"ruby\" -*- */"
567
- valid << "// coding: utf-8"
568
- valid << "// -*- coding: utf-8; c-file-style: \"ruby\" -*-"
569
- invalid = []
570
- {:to => valid, :not_to => invalid}.each do |msg, list|
571
- list.each do |src|
572
- Registry.clear
573
- parser = Parser::SourceParser.new
574
- expect(File).to receive(:read_binary).with('tmpfile.c').and_return(src)
575
- result = parser.parse("tmpfile.c")
576
- content = result.instance_variable_get("@content")
577
- expect(['UTF-8']).send(msg, include(content.encoding.to_s))
578
- end
579
- end
580
- end if YARD.ruby19?
581
-
582
- Parser::SourceParser::ENCODING_BYTE_ORDER_MARKS.each do |encoding, bom|
583
- it "understands #{encoding.upcase} BOM" do
584
- parser = Parser::SourceParser.new
585
- src = bom + String.new("class FooBar; end").force_encoding('binary')
586
- src.force_encoding('binary')
587
- expect(File).to receive(:read_binary).with('tmpfile').and_return(src)
588
- result = parser.parse('tmpfile')
589
- expect(Registry.all(:class).first.path).to eq "FooBar"
590
- expect(result.enumerator[0].source.encoding.to_s.downcase).to eq encoding
591
- end
592
- end if HAVE_RIPPER && YARD.ruby19?
593
- end
594
-
595
- describe "#parse_in_order" do
596
- def in_order_parse(*files)
597
- paths = files.map {|f| File.join(File.dirname(__FILE__), 'examples', f.to_s + '.rb.txt') }
598
- YARD::Parser::SourceParser.parse(paths, [], Logger::DEBUG)
599
- end
600
-
601
- it "attempts to parse files in order" do
602
- log.enter_level(Logger::DEBUG) do
603
- msgs = []
604
- expect(log).to receive(:debug) {|m| msgs << m }.at_least(:once)
605
- allow(log).to receive(:<<)
606
- in_order_parse 'parse_in_order_001', 'parse_in_order_002'
607
- expect(msgs[1]).to match(/Parsing .+parse_in_order_001.+/)
608
- expect(msgs[2]).to match(/Missing object MyModule/)
609
- expect(msgs[3]).to match(/Parsing .+parse_in_order_002.+/)
610
- expect(msgs[4]).to match(/Re-processing .+parse_in_order_001.+/)
611
- end
612
- end
613
-
614
- it "attempts to order files by length for globs (process toplevel files first)" do
615
- files = %w(a a/b a/b/c)
616
- files.each do |file|
617
- expect(File).to receive(:file?).with(file).and_return(true)
618
- expect(File).to receive(:read_binary).with(file).ordered.and_return('')
619
- end
620
- expect(Dir).to receive(:[]).with('a/**/*').and_return(files.reverse)
621
- YARD.parse 'a/**/*'
622
- end
623
-
624
- it "allows overriding of length sorting when single file is presented" do
625
- files = %w(a/b/c a a/b)
626
- files.each do |file|
627
- expect(File).to receive(:file?).with(file).at_least(1).times.and_return(true)
628
- expect(File).to receive(:read_binary).with(file).ordered.and_return('')
629
- end
630
- expect(Dir).to receive(:[]).with('a/**/*').and_return(files.reverse)
631
- YARD.parse ['a/b/c', 'a/**/*']
632
- end
633
- end
634
-
635
- describe "#parse_statements" do
636
- before do
637
- Registry.clear
638
- end
639
-
640
- it "displays a warning for invalid parser type" do
641
- expect(log).to receive(:warn).with(/unrecognized file/)
642
- expect(log).to receive(:backtrace)
643
- YARD::Parser::SourceParser.parse_string("int main() { }", :d)
644
- end
645
-
646
- if HAVE_RIPPER
647
- it "displays a warning for a syntax error (with new parser)" do
648
- expect(log).to receive(:warn).with(/Syntax error in/)
649
- expect(log).to receive(:backtrace)
650
- YARD::Parser::SourceParser.parse_string("%!!!", :ruby)
651
- end
652
- end
653
-
654
- it "handles groups" do
655
- YARD.parse_string <<-eof
656
- class A
657
- # @group Group Name
658
- def foo; end
659
- def foo2; end
660
-
661
- # @endgroup
662
-
663
- def bar; end
664
-
665
- # @group Group 2
666
- def baz; end
667
- end
668
- eof
669
-
670
- expect(Registry.at('A').groups).to eq ['Group Name', 'Group 2']
671
- expect(Registry.at('A#bar').group).to be nil
672
- expect(Registry.at('A#foo').group).to eq "Group Name"
673
- expect(Registry.at('A#foo2').group).to eq "Group Name"
674
- expect(Registry.at('A#baz').group).to eq "Group 2"
675
- end
676
-
677
- it "handles multi-line class/module references" do
678
- YARD.parse_string <<-eof
679
- class A::
680
- B::C; end
681
- eof
682
- expect(Registry.all).to eq [P('A::B::C')]
683
- end
684
-
685
- it "handles sclass definitions of multi-line class/module references" do
686
- YARD.parse_string <<-eof
687
- class << A::
688
- B::C
689
- def foo; end
690
- end
691
- eof
692
- expect(Registry.all.size).to eq 2
693
- expect(Registry.at('A::B::C')).not_to be nil
694
- expect(Registry.at('A::B::C.foo')).not_to be nil
695
- end
696
-
697
- it "handles lone comment blocks at the end of a namespace" do
698
- YARD.parse_string <<-eof
699
- module A
700
- class B
701
- def c; end
702
-
703
- # @!method d
704
- end
705
- end
706
- eof
707
- expect(Registry.at('A#d')).to be nil
708
- expect(Registry.at('A::B#d')).not_to be nil
709
- end
710
-
711
- if YARD.ruby2?
712
- it "supports named arguments with default values" do
713
- YARD.parse_string 'def foo(a, b = 1, *c, d, e: 3, **f, &g) end'
714
- args = [['a', nil], ['b', '1'], ['*c', nil], ['d', nil], ['e:', '3'], ['**f', nil], ['&g', nil]]
715
- expect(Registry.at('#foo').parameters).to eq(args)
716
- end
717
- end
718
-
719
- if NAMED_OPTIONAL_ARGUMENTS && !LEGACY_PARSER
720
- it "supports named arguments without default values" do
721
- YARD.parse_string 'def foo(a, b = 1, *c, d, e: 3, f:, **g, &h) end'
722
- args = [['a', nil], ['b', '1'], ['*c', nil], ['d', nil], ['e:', '3'], ['f:', nil], ['**g', nil], ['&h', nil]]
723
- expect(Registry.at('#foo').parameters).to eq(args)
724
- end
725
- end
726
- end
727
- end
1
+ # frozen_string_literal: true
2
+
3
+ class MyParser < Parser::Base; end
4
+
5
+ RSpec.shared_examples_for "parser type registration" do
6
+ after do
7
+ Parser::SourceParser.parser_types.delete(:my_parser)
8
+ Parser::SourceParser.parser_type_extensions.delete(:my_parser)
9
+ end
10
+ end
11
+
12
+ RSpec.describe YARD::Parser::SourceParser do
13
+ before do
14
+ Registry.clear
15
+ end
16
+
17
+ def parse_list(*list)
18
+ files = list.map do |v|
19
+ filename, source = *v
20
+ allow(File).to receive(:read_binary).with(filename).and_return(source)
21
+ filename
22
+ end
23
+ Parser::SourceParser.send(:parse_in_order, *files)
24
+ end
25
+
26
+ def before_list(&block)
27
+ Parser::SourceParser.before_parse_list(&block)
28
+ end
29
+
30
+ def after_list(&block)
31
+ Parser::SourceParser.after_parse_list(&block)
32
+ end
33
+
34
+ def before_file(&block)
35
+ Parser::SourceParser.before_parse_file(&block)
36
+ end
37
+
38
+ def after_file(&block)
39
+ Parser::SourceParser.after_parse_file(&block)
40
+ end
41
+
42
+ describe ".before_parse_list" do
43
+ before do
44
+ Parser::SourceParser.before_parse_list_callbacks.clear
45
+ Parser::SourceParser.after_parse_list_callbacks.clear
46
+ end
47
+
48
+ it "handles basic callback support" do
49
+ before_list do |files, globals|
50
+ expect(files).to eq ['foo.rb', 'bar.rb']
51
+ expect(globals).to eq OpenStruct.new
52
+ end
53
+ parse_list ['foo.rb', 'foo!'], ['bar.rb', 'class Foo; end']
54
+ expect(Registry.at('Foo')).not_to be nil
55
+ end
56
+
57
+ it "supports multiple callbacks" do
58
+ checks = []
59
+ before_list { checks << :one }
60
+ before_list { checks << :two }
61
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
62
+ expect(Registry.at('Foo')).not_to be nil
63
+ expect(checks).to eq [:one, :two]
64
+ end
65
+
66
+ it "cancels parsing if it returns false" do
67
+ checks = []
68
+ before_list { checks << :one }
69
+ before_list { false }
70
+ before_list { checks << :three }
71
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
72
+ expect(Registry.at('Foo')).to be nil
73
+ expect(checks).to eq [:one]
74
+ end
75
+
76
+ it "does not cancel on nil" do
77
+ checks = []
78
+ before_list { checks << :one }
79
+ before_list { nil }
80
+ before_list { checks << :two }
81
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
82
+ expect(Registry.at('Foo')).not_to be nil
83
+ expect(checks).to eq [:one, :two]
84
+ end
85
+
86
+ it "passes in globals" do
87
+ before_list {|_f, g| g.x = 1 }
88
+ before_list {|_f, g| g.x += 1 }
89
+ before_list {|_f, g| g.x += 1 }
90
+ after_list {|_f, g| expect(g.x).to eq 3 }
91
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
92
+ expect(Registry.at('Foo')).not_to be nil
93
+ end
94
+ end
95
+
96
+ describe ".after_parse_list" do
97
+ before do
98
+ Parser::SourceParser.before_parse_list_callbacks.clear
99
+ Parser::SourceParser.after_parse_list_callbacks.clear
100
+ end
101
+
102
+ it "handles basic callback support and maintain files/globals" do
103
+ before_list {|_f, g| g.foo = :bar }
104
+ after_list do |files, globals|
105
+ expect(files).to eq ['foo.rb', 'bar.rb']
106
+ expect(globals.foo).to eq :bar
107
+ end
108
+ parse_list ['foo.rb', 'foo!'], ['bar.rb', 'class Foo; end']
109
+ expect(Registry.at('Foo')).not_to be nil
110
+ end
111
+
112
+ it "supports multiple callbacks" do
113
+ checks = []
114
+ after_list { checks << :one }
115
+ after_list { checks << :two }
116
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
117
+ expect(Registry.at('Foo')).not_to be nil
118
+ expect(checks).to eq [:one, :two]
119
+ end
120
+
121
+ it "does not cancel parsing if it returns false" do
122
+ checks = []
123
+ after_list { checks << :one }
124
+ after_list { false }
125
+ after_list { checks << :three }
126
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
127
+ expect(Registry.at('Foo')).not_to be nil
128
+ expect(checks).to eq [:one, :three]
129
+ end
130
+ end
131
+
132
+ describe ".before_parse_file" do
133
+ before do
134
+ Parser::SourceParser.before_parse_file_callbacks.clear
135
+ Parser::SourceParser.after_parse_file_callbacks.clear
136
+ end
137
+
138
+ it "handles basic callback support" do
139
+ before_file do |parser|
140
+ expect(parser.contents).to eq 'class Foo; end'
141
+ expect(parser.file).to match(/(foo|bar)\.rb/)
142
+ end
143
+ parse_list ['foo.rb', 'class Foo; end'], ['bar.rb', 'class Foo; end']
144
+ expect(Registry.at('Foo')).not_to be nil
145
+ end
146
+
147
+ it "supports multiple callbacks" do
148
+ checks = []
149
+ before_file { checks << :one }
150
+ before_file { checks << :two }
151
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
152
+ expect(Registry.at('Foo')).not_to be nil
153
+ expect(checks).to eq [:one, :two, :one, :two, :one, :two]
154
+ end
155
+
156
+ it "cancels parsing if it returns false" do
157
+ checks = []
158
+ before_file { checks << :one }
159
+ before_file { false }
160
+ before_file { checks << :three }
161
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
162
+ expect(Registry.at('Foo')).to be nil
163
+ expect(checks).to eq [:one, :one, :one]
164
+ end
165
+
166
+ it "does not cancel on nil" do
167
+ checks = []
168
+ before_file { checks << :one }
169
+ before_file { nil }
170
+ before_file { checks << :two }
171
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
172
+ expect(Registry.at('Foo')).not_to be nil
173
+ expect(checks).to eq [:one, :two, :one, :two, :one, :two]
174
+ end
175
+ end
176
+
177
+ describe ".after_parse_file" do
178
+ before do
179
+ Parser::SourceParser.before_parse_file_callbacks.clear
180
+ Parser::SourceParser.after_parse_file_callbacks.clear
181
+ end
182
+
183
+ it "handles basic callback support" do
184
+ after_file do |parser|
185
+ expect(parser.contents).to eq 'class Foo; end'
186
+ expect(parser.file).to match(/(foo|bar)\.rb/)
187
+ end
188
+ parse_list ['foo.rb', 'class Foo; end'], ['bar.rb', 'class Foo; end']
189
+ expect(Registry.at('Foo')).not_to be nil
190
+ end
191
+
192
+ it "supports multiple callbacks" do
193
+ checks = []
194
+ after_file { checks << :one }
195
+ after_file { checks << :two }
196
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
197
+ expect(Registry.at('Foo')).not_to be nil
198
+ expect(checks).to eq [:one, :two, :one, :two, :one, :two]
199
+ end
200
+
201
+ it "does not cancel parsing if it returns false" do
202
+ checks = []
203
+ after_file { checks << :one }
204
+ after_file { false }
205
+ after_file { checks << :three }
206
+ parse_list ['file.rb', ''], ['file2.rb', ''], ['file3.rb', 'class Foo; end']
207
+ expect(Registry.at('Foo')).not_to be nil
208
+ expect(checks).to eq [:one, :three, :one, :three, :one, :three]
209
+ end
210
+ end
211
+
212
+ describe ".register_parser_type" do
213
+ it_should_behave_like "parser type registration"
214
+
215
+ it "registers a subclass of Parser::Base" do
216
+ parser = double(:parser)
217
+ expect(parser).to receive(:parse)
218
+ expect(MyParser).to receive(:new).with('content', '(stdin)').and_return(parser)
219
+ Parser::SourceParser.register_parser_type(:my_parser, MyParser, 'myparser')
220
+ Parser::SourceParser.parse_string('content', :my_parser)
221
+ end
222
+
223
+ it "requires class to be a subclass of Parser::Base" do
224
+ expect { Parser::SourceParser.register_parser_type(:my_parser, String) }.to raise_error(ArgumentError)
225
+ expect { Parser::SourceParser.register_parser_type(:my_parser, Parser::Base) }.to raise_error(ArgumentError)
226
+ end
227
+ end
228
+
229
+ describe ".parser_type_for_extension" do
230
+ it_should_behave_like "parser type registration"
231
+
232
+ it "finds an extension in a registered array of extensions" do
233
+ Parser::SourceParser.register_parser_type(:my_parser, MyParser, ['a', 'b', 'd'])
234
+ expect(Parser::SourceParser.parser_type_for_extension('a')).to eq :my_parser
235
+ expect(Parser::SourceParser.parser_type_for_extension('b')).to eq :my_parser
236
+ expect(Parser::SourceParser.parser_type_for_extension('d')).to eq :my_parser
237
+ expect(Parser::SourceParser.parser_type_for_extension('c')).not_to eq :my_parser
238
+ end
239
+
240
+ it "finds an extension in a Regexp" do
241
+ Parser::SourceParser.register_parser_type(:my_parser, MyParser, /abc$/)
242
+ expect(Parser::SourceParser.parser_type_for_extension('dabc')).to eq :my_parser
243
+ expect(Parser::SourceParser.parser_type_for_extension('dabcd')).not_to eq :my_parser
244
+ end
245
+
246
+ it "finds an extension in a list of Regexps" do
247
+ Parser::SourceParser.register_parser_type(:my_parser, MyParser, [/ab$/, /abc$/])
248
+ expect(Parser::SourceParser.parser_type_for_extension('dabc')).to eq :my_parser
249
+ expect(Parser::SourceParser.parser_type_for_extension('dabcd')).not_to eq :my_parser
250
+ end
251
+
252
+ it "finds an extension in a String" do
253
+ Parser::SourceParser.register_parser_type(:my_parser, MyParser, "abc")
254
+ expect(Parser::SourceParser.parser_type_for_extension('abc')).to eq :my_parser
255
+ expect(Parser::SourceParser.parser_type_for_extension('abcd')).not_to eq :my_parser
256
+ end
257
+ end
258
+
259
+ describe "#parse_string" do
260
+ it "parses basic Ruby code" do
261
+ YARD.parse_string(<<-eof)
262
+ module Hello
263
+ class Hi
264
+ # Docstring
265
+ # Docstring2
266
+ def me; "VALUE" end
267
+ end
268
+ end
269
+ eof
270
+ expect(Registry.at(:Hello)).not_to eq nil
271
+ expect(Registry.at("Hello::Hi#me")).not_to eq nil
272
+ expect(Registry.at("Hello::Hi#me").docstring).to eq "Docstring\nDocstring2"
273
+ expect(Registry.at("Hello::Hi#me").docstring.line_range).to eq(3..4)
274
+ end
275
+
276
+ it "parses Ruby code with metaclasses" do
277
+ YARD.parse_string(<<-eof)
278
+ module Hello
279
+ class Hi
280
+ class <<self
281
+ # Docstring
282
+ def me; "VALUE" end
283
+ end
284
+ end
285
+ end
286
+ eof
287
+ expect(Registry.at(:Hello)).not_to eq nil
288
+ expect(Registry.at("Hello::Hi.me")).not_to eq nil
289
+ expect(Registry.at("Hello::Hi.me").docstring).to eq "Docstring"
290
+ end
291
+
292
+ it "only uses prepended comments for an object" do
293
+ YARD.parse_string(<<-eof)
294
+ # Test
295
+
296
+ # PASS
297
+ module Hello
298
+ end # FAIL
299
+ eof
300
+ expect(Registry.at(:Hello).docstring).to eq "PASS"
301
+ end
302
+
303
+ it "does not add comments appended to last line of block" do
304
+ YARD.parse_string <<-eof
305
+ module Hello2
306
+ end # FAIL
307
+ eof
308
+ expect(Registry.at(:Hello2).docstring).to be_blank
309
+ end
310
+
311
+ it "adds comments appended to an object's first line" do
312
+ YARD.parse_string <<-eof
313
+ module Hello # PASS
314
+ HELLO
315
+ end
316
+
317
+ module Hello2 # PASS
318
+ # ANOTHER PASS
319
+ def x; end
320
+ end
321
+ eof
322
+
323
+ expect(Registry.at(:Hello).docstring).to eq "PASS"
324
+ expect(Registry.at(:Hello2).docstring).to eq "PASS"
325
+ expect(Registry.at('Hello2#x').docstring).to eq "ANOTHER PASS"
326
+ end
327
+
328
+ it "takes preceding comments only if they exist" do
329
+ YARD.parse_string <<-eof
330
+ # PASS
331
+ module Hello # FAIL
332
+ HELLO
333
+ end
334
+ eof
335
+
336
+ expect(Registry.at(:Hello).docstring).to eq "PASS"
337
+ end
338
+
339
+ it "strips all hashes prefixed on comment line" do
340
+ YARD.parse_string(<<-eof)
341
+ ### PASS
342
+ #### PASS
343
+ ##### PASS
344
+ module Hello
345
+ end
346
+ eof
347
+ expect(Registry.at(:Hello).docstring).to eq "PASS\nPASS\nPASS"
348
+ end
349
+
350
+ it "handles =begin/=end style comments" do
351
+ YARD.parse_string "=begin\nfoo\nbar\n=end\nclass Foo; end\n"
352
+ expect(Registry.at(:Foo).docstring).to eq "foo\nbar"
353
+
354
+ YARD.parse_string "=begin\n\nfoo\nbar\n=end\nclass Foo; end\n"
355
+ expect(Registry.at(:Foo).docstring).to eq "foo\nbar"
356
+
357
+ YARD.parse_string "=begin\nfoo\n\nbar\n=end\nclass Foo; end\n"
358
+ expect(Registry.at(:Foo).docstring).to eq "foo\n\nbar"
359
+ end
360
+
361
+ it "knows about docstrings starting with ##" do
362
+ {'#' => false, '##' => true}.each do |hash, expected|
363
+ YARD.parse_string "#{hash}\n# Foo bar\nclass Foo; end"
364
+ expect(Registry.at(:Foo).docstring.hash_flag).to eq expected
365
+ end
366
+ end
367
+
368
+ it "removes shebang from initial file comments" do
369
+ YARD.parse_string "#!/bin/ruby\n# this is a comment\nclass Foo; end"
370
+ expect(Registry.at(:Foo).docstring).to eq "this is a comment"
371
+ end
372
+
373
+ it "removes encoding line from initial file comments" do
374
+ YARD.parse_string "# encoding: utf-8\n# this is a comment\nclass Foo; end"
375
+ expect(Registry.at(:Foo).docstring).to eq "this is a comment"
376
+ end
377
+
378
+ it "adds macros on any object" do
379
+ YARD.parse_string <<-eof
380
+ # @!macro [new] foo
381
+ # This is a macro
382
+ # @return [String] the string
383
+ class Foo
384
+ # @!macro foo
385
+ def foo; end
386
+ end
387
+ eof
388
+
389
+ macro = CodeObjects::MacroObject.find('foo')
390
+ expect(macro.macro_data).to eq "This is a macro\n@return [String] the string"
391
+ expect(Registry.at('Foo').docstring.to_raw).to eq macro.macro_data
392
+ expect(Registry.at('Foo#foo').docstring.to_raw).to eq macro.macro_data
393
+ end
394
+
395
+ it "allows directives parsed on lone comments" do
396
+ YARD.parse_string(<<-eof)
397
+ class Foo
398
+ # @!method foo(a = "hello")
399
+ # @!scope class
400
+ # @!visibility private
401
+ # @param [String] a the name of the foo
402
+ # @return [Symbol] the symbolized foo
403
+
404
+ # @!method bar(value)
405
+ end
406
+ eof
407
+ foo = Registry.at('Foo.foo')
408
+ bar = Registry.at('Foo#bar')
409
+ expect(foo).not_to be nil
410
+ expect(foo.visibility).to eq :private
411
+ expect(foo.tag(:param).name).to eq 'a'
412
+ expect(foo.tag(:return).types).to eq ['Symbol']
413
+ expect(bar).not_to be nil
414
+ expect(bar.signature).to eq 'def bar(value)'
415
+ end
416
+
417
+ it "parses lone comments at end of blocks" do
418
+ YARD.parse_string(<<-eof)
419
+ class Foo
420
+ none
421
+
422
+ # @!method foo(a = "hello")
423
+ end
424
+ eof
425
+ foo = Registry.at('Foo#foo')
426
+ expect(foo).not_to be nil
427
+ expect(foo.signature).to eq 'def foo(a = "hello")'
428
+ end
429
+
430
+ it "handles lone comment with no code" do
431
+ YARD.parse_string '# @!method foo(a = "hello")'
432
+ foo = Registry.at('#foo')
433
+ expect(foo).not_to be nil
434
+ expect(foo.signature).to eq 'def foo(a = "hello")'
435
+ end
436
+
437
+ it "handles non-ASCII encoding in heredoc" do
438
+ YARD.parse_string <<-eof
439
+ # encoding: utf-8
440
+
441
+ heredoc <<-ending
442
+ foo\u{ffe2} bar.
443
+ ending
444
+
445
+ # Hello \u{ffe2} world
446
+ class Foo < Bar
447
+ attr_accessor :foo
448
+ end
449
+ eof
450
+ expect(Registry.at('Foo').superclass).to eq P('Bar')
451
+ end
452
+ end
453
+
454
+ describe "#parse" do
455
+ it "parses a basic Ruby file" do
456
+ parse_file :example1, __FILE__
457
+ expect(Registry.at(:Hello)).not_to eq nil
458
+ expect(Registry.at("Hello::Hi#me")).not_to eq nil
459
+ expect(Registry.at("Hello::Hi#me").docstring).to eq "Docstring"
460
+ end
461
+
462
+ it "parses a set of file globs" do
463
+ expect(Dir).to receive(:[]).with('lib/**/*.rb').and_return([])
464
+ YARD.parse('lib/**/*.rb')
465
+ end
466
+
467
+ it "parses a set of absolute paths" do
468
+ expect(Dir).not_to receive(:[])
469
+ expect(File).to receive(:file?).with('/path/to/file').and_return(true)
470
+ expect(File).to receive(:read_binary).with('/path/to/file').and_return("")
471
+ YARD.parse('/path/to/file')
472
+ end
473
+
474
+ it "cleans paths before parsing" do
475
+ expect(File).to receive(:open).and_return("")
476
+ parser = Parser::SourceParser.new(:ruby, true)
477
+ parser.parse('a//b//c')
478
+ expect(parser.file).to eq 'a/b/c'
479
+ end
480
+
481
+ it "parses files with '*' in them as globs and others as absolute paths" do
482
+ expect(Dir).to receive(:[]).with('*.rb').and_return(['a.rb', 'b.rb'])
483
+ expect(File).to receive(:file?).with('/path/to/file').and_return(true)
484
+ expect(File).to receive(:file?).with('a.rb').and_return(true)
485
+ expect(File).to receive(:file?).with('b.rb').and_return(true)
486
+ expect(File).to receive(:read_binary).with('/path/to/file').and_return("")
487
+ expect(File).to receive(:read_binary).with('a.rb').and_return("")
488
+ expect(File).to receive(:read_binary).with('b.rb').and_return("")
489
+ YARD.parse ['/path/to/file', '*.rb']
490
+ end
491
+
492
+ it "converts directories into globs" do
493
+ expect(Dir).to receive(:[]).with('foo/**/*.{rb,c,cc,cxx,cpp}').and_return(['foo/a.rb', 'foo/bar/b.rb'])
494
+ expect(File).to receive(:directory?).with('foo').and_return(true)
495
+ expect(File).to receive(:file?).with('foo/a.rb').and_return(true)
496
+ expect(File).to receive(:file?).with('foo/bar/b.rb').and_return(true)
497
+ expect(File).to receive(:read_binary).with('foo/a.rb').and_return("")
498
+ expect(File).to receive(:read_binary).with('foo/bar/b.rb').and_return("")
499
+ YARD.parse ['foo']
500
+ end
501
+
502
+ it "uses Registry.checksums cache if file is cached" do
503
+ data = 'DATA'
504
+ hash = Registry.checksum_for(data)
505
+ cmock = double(:cmock)
506
+ expect(cmock).to receive(:[]).with('foo/bar').and_return(hash)
507
+ expect(Registry).to receive(:checksums).and_return(cmock)
508
+ expect(File).to receive(:file?).with('foo/bar').and_return(true)
509
+ expect(File).to receive(:read_binary).with('foo/bar').and_return(data)
510
+ YARD.parse('foo/bar')
511
+ end
512
+
513
+ it "supports excluded paths" do
514
+ expect(File).to receive(:file?).with('foo/bar').and_return(true)
515
+ expect(File).to receive(:file?).with('foo/baz').and_return(true)
516
+ expect(File).not_to receive(:read_binary)
517
+ YARD.parse(["foo/bar", "foo/baz"], ["foo", /baz$/])
518
+ end
519
+
520
+ it "converts file contents to proper encoding if coding line is present" do
521
+ valid = []
522
+ valid << "# encoding: sjis"
523
+ valid << "# encoding: utf-8"
524
+ valid << "# xxxxxencoding: sjis"
525
+ valid << "# xxxxxencoding: sjis xxxxxx"
526
+ valid << "# ENCODING: sjis"
527
+ valid << "#coDiNG: sjis"
528
+ valid << "# -*- coding: sjis -*-"
529
+ valid << "# -*- coding: utf-8; indent-tabs-mode: nil"
530
+ valid << "### coding: sjis"
531
+ valid << "# encoding=sjis"
532
+ valid << "# encoding:sjis"
533
+ valid << "# encoding = sjis"
534
+ valid << "# encoding == sjis"
535
+ valid << "# encoding : sjis"
536
+ valid << "# encoding :: sjis"
537
+ valid << "#!/bin/shebang\n# encoding: sjis"
538
+ valid << "#!/bin/shebang\r\n# coding: sjis"
539
+ invalid = []
540
+ invalid << "#\n# encoding: sjis"
541
+ invalid << "#!/bin/shebang\n#\n# encoding: sjis"
542
+ invalid << "# !/bin/shebang\n# encoding: sjis"
543
+ {:to => valid, :not_to => invalid}.each do |msg, list|
544
+ list.each do |src|
545
+ Registry.clear
546
+ parser = Parser::SourceParser.new
547
+ expect(File).to receive(:read_binary).with('tmpfile').and_return(src)
548
+ result = parser.parse("tmpfile")
549
+ if HAVE_RIPPER && YARD.ruby19?
550
+ if msg == :not_to
551
+ default_encoding = 'UTF-8'
552
+ expect(result.enumerator[0].source.encoding.to_s).to eq(default_encoding)
553
+ else
554
+ expect(['Shift_JIS', 'Windows-31J', 'UTF-8']).send(msg,
555
+ include(result.enumerator[0].source.encoding.to_s))
556
+ end
557
+ end
558
+ expect(result.encoding_line).send(msg, eq(src.split("\n").last))
559
+ end
560
+ end
561
+ end
562
+
563
+ it "converts C file contents to proper encoding if coding line is present" do
564
+ valid = []
565
+ valid << "/* coding: utf-8 */"
566
+ valid << "/* -*- coding: utf-8; c-file-style: \"ruby\" -*- */"
567
+ valid << "// coding: utf-8"
568
+ valid << "// -*- coding: utf-8; c-file-style: \"ruby\" -*-"
569
+ invalid = []
570
+ {:to => valid, :not_to => invalid}.each do |msg, list|
571
+ list.each do |src|
572
+ Registry.clear
573
+ parser = Parser::SourceParser.new
574
+ expect(File).to receive(:read_binary).with('tmpfile.c').and_return(src)
575
+ result = parser.parse("tmpfile.c")
576
+ content = result.instance_variable_get("@content")
577
+ expect(['UTF-8']).send(msg, include(content.encoding.to_s))
578
+ end
579
+ end
580
+ end if YARD.ruby19?
581
+
582
+ Parser::SourceParser::ENCODING_BYTE_ORDER_MARKS.each do |encoding, bom|
583
+ it "understands #{encoding.upcase} BOM" do
584
+ parser = Parser::SourceParser.new
585
+ src = bom + String.new("class FooBar; end").force_encoding('binary')
586
+ src.force_encoding('binary')
587
+ expect(File).to receive(:read_binary).with('tmpfile').and_return(src)
588
+ result = parser.parse('tmpfile')
589
+ expect(Registry.all(:class).first.path).to eq "FooBar"
590
+ expect(result.enumerator[0].source.encoding.to_s.downcase).to eq encoding
591
+ end
592
+ end if HAVE_RIPPER && YARD.ruby19?
593
+ end
594
+
595
+ describe "#parse_in_order" do
596
+ def in_order_parse(*files)
597
+ paths = files.map {|f| File.join(File.dirname(__FILE__), 'examples', f.to_s + '.rb.txt') }
598
+ YARD::Parser::SourceParser.parse(paths, [], Logger::DEBUG)
599
+ end
600
+
601
+ it "attempts to parse files in order" do
602
+ log.enter_level(Logger::DEBUG) do
603
+ msgs = []
604
+ expect(log).to receive(:debug) {|m| msgs << m }.at_least(:once)
605
+ allow(log).to receive(:<<)
606
+ in_order_parse 'parse_in_order_001', 'parse_in_order_002'
607
+ expect(msgs[1]).to match(/Parsing .+parse_in_order_001.+/)
608
+ expect(msgs[2]).to match(/Missing object MyModule/)
609
+ expect(msgs[3]).to match(/Parsing .+parse_in_order_002.+/)
610
+ expect(msgs[4]).to match(/Re-processing .+parse_in_order_001.+/)
611
+ end
612
+ end
613
+
614
+ it "attempts to order files by length for globs (process toplevel files first)" do
615
+ files = %w(a a/b a/b/c)
616
+ files.each do |file|
617
+ expect(File).to receive(:file?).with(file).and_return(true)
618
+ expect(File).to receive(:read_binary).with(file).ordered.and_return('')
619
+ end
620
+ expect(Dir).to receive(:[]).with('a/**/*').and_return(files.reverse)
621
+ YARD.parse 'a/**/*'
622
+ end
623
+
624
+ it "allows overriding of length sorting when single file is presented" do
625
+ files = %w(a/b/c a a/b)
626
+ files.each do |file|
627
+ expect(File).to receive(:file?).with(file).at_least(1).times.and_return(true)
628
+ expect(File).to receive(:read_binary).with(file).ordered.and_return('')
629
+ end
630
+ expect(Dir).to receive(:[]).with('a/**/*').and_return(files.reverse)
631
+ YARD.parse ['a/b/c', 'a/**/*']
632
+ end
633
+ end
634
+
635
+ describe "#parse_statements" do
636
+ before do
637
+ Registry.clear
638
+ end
639
+
640
+ it "displays a warning for invalid parser type" do
641
+ expect(log).to receive(:warn).with(/unrecognized file/)
642
+ expect(log).to receive(:backtrace)
643
+ YARD::Parser::SourceParser.parse_string("int main() { }", :d)
644
+ end
645
+
646
+ if HAVE_RIPPER
647
+ it "displays a warning for a syntax error (with new parser)" do
648
+ expect(log).to receive(:warn).with(/Syntax error in/)
649
+ expect(log).to receive(:backtrace)
650
+ YARD::Parser::SourceParser.parse_string("%!!!", :ruby)
651
+ end
652
+ end
653
+
654
+ it "handles groups" do
655
+ YARD.parse_string <<-eof
656
+ class A
657
+ # @group Group Name
658
+ def foo; end
659
+ def foo2; end
660
+
661
+ # @endgroup
662
+
663
+ def bar; end
664
+
665
+ # @group Group 2
666
+ def baz; end
667
+ end
668
+ eof
669
+
670
+ expect(Registry.at('A').groups).to eq ['Group Name', 'Group 2']
671
+ expect(Registry.at('A#bar').group).to be nil
672
+ expect(Registry.at('A#foo').group).to eq "Group Name"
673
+ expect(Registry.at('A#foo2').group).to eq "Group Name"
674
+ expect(Registry.at('A#baz').group).to eq "Group 2"
675
+ end
676
+
677
+ it "handles multi-line class/module references" do
678
+ YARD.parse_string <<-eof
679
+ class A::
680
+ B::C; end
681
+ eof
682
+ expect(Registry.all).to eq [P('A::B::C')]
683
+ end
684
+
685
+ it "handles sclass definitions of multi-line class/module references" do
686
+ YARD.parse_string <<-eof
687
+ class << A::
688
+ B::C
689
+ def foo; end
690
+ end
691
+ eof
692
+ expect(Registry.all.size).to eq 2
693
+ expect(Registry.at('A::B::C')).not_to be nil
694
+ expect(Registry.at('A::B::C.foo')).not_to be nil
695
+ end
696
+
697
+ it "handles lone comment blocks at the end of a namespace" do
698
+ YARD.parse_string <<-eof
699
+ module A
700
+ class B
701
+ def c; end
702
+
703
+ # @!method d
704
+ end
705
+ end
706
+ eof
707
+ expect(Registry.at('A#d')).to be nil
708
+ expect(Registry.at('A::B#d')).not_to be nil
709
+ end
710
+
711
+ if YARD.ruby2?
712
+ it "supports named arguments with default values" do
713
+ YARD.parse_string 'def foo(a, b = 1, *c, d, e: 3, **f, &g) end'
714
+ args = [['a', nil], ['b', '1'], ['*c', nil], ['d', nil], ['e:', '3'], ['**f', nil], ['&g', nil]]
715
+ expect(Registry.at('#foo').parameters).to eq(args)
716
+ end
717
+ end
718
+
719
+ if NAMED_OPTIONAL_ARGUMENTS && !LEGACY_PARSER
720
+ it "supports named arguments without default values" do
721
+ YARD.parse_string 'def foo(a, b = 1, *c, d, e: 3, f:, **g, &h) end'
722
+ args = [['a', nil], ['b', '1'], ['*c', nil], ['d', nil], ['e:', '3'], ['f:', nil], ['**g', nil], ['&h', nil]]
723
+ expect(Registry.at('#foo').parameters).to eq(args)
724
+ end
725
+ end
726
+ end
727
+ end