yard 0.9.18 → 0.9.19

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 (567) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +26 -26
  3. data/CHANGELOG.md +742 -728
  4. data/LEGAL +66 -66
  5. data/LICENSE +22 -22
  6. data/README.md +328 -328
  7. data/Rakefile +42 -53
  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 +308 -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 +789 -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 -615
  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 +134 -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 +11 -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 -386
  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 +212 -211
  95. data/lib/yard/handlers/c/init_handler.rb +20 -20
  96. data/lib/yard/handlers/c/method_handler.rb +45 -45
  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/common/method_handler.rb +19 -0
  104. data/lib/yard/handlers/processor.rb +200 -200
  105. data/lib/yard/handlers/ruby/alias_handler.rb +44 -44
  106. data/lib/yard/handlers/ruby/attribute_handler.rb +87 -87
  107. data/lib/yard/handlers/ruby/base.rb +165 -165
  108. data/lib/yard/handlers/ruby/class_condition_handler.rb +92 -92
  109. data/lib/yard/handlers/ruby/class_handler.rb +119 -119
  110. data/lib/yard/handlers/ruby/class_variable_handler.rb +17 -17
  111. data/lib/yard/handlers/ruby/comment_handler.rb +10 -10
  112. data/lib/yard/handlers/ruby/constant_handler.rb +59 -59
  113. data/lib/yard/handlers/ruby/decorator_handler_methods.rb +123 -123
  114. data/lib/yard/handlers/ruby/dsl_handler.rb +15 -15
  115. data/lib/yard/handlers/ruby/dsl_handler_methods.rb +96 -96
  116. data/lib/yard/handlers/ruby/exception_handler.rb +27 -27
  117. data/lib/yard/handlers/ruby/extend_handler.rb +22 -22
  118. data/lib/yard/handlers/ruby/legacy/alias_handler.rb +37 -37
  119. data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +65 -65
  120. data/lib/yard/handlers/ruby/legacy/base.rb +245 -245
  121. data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +83 -83
  122. data/lib/yard/handlers/ruby/legacy/class_handler.rb +113 -113
  123. data/lib/yard/handlers/ruby/legacy/class_variable_handler.rb +15 -15
  124. data/lib/yard/handlers/ruby/legacy/comment_handler.rb +10 -10
  125. data/lib/yard/handlers/ruby/legacy/constant_handler.rb +29 -29
  126. data/lib/yard/handlers/ruby/legacy/dsl_handler.rb +17 -17
  127. data/lib/yard/handlers/ruby/legacy/exception_handler.rb +13 -13
  128. data/lib/yard/handlers/ruby/legacy/extend_handler.rb +21 -21
  129. data/lib/yard/handlers/ruby/legacy/method_handler.rb +90 -90
  130. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +39 -39
  131. data/lib/yard/handlers/ruby/legacy/module_function_handler.rb +19 -19
  132. data/lib/yard/handlers/ruby/legacy/module_handler.rb +12 -12
  133. data/lib/yard/handlers/ruby/legacy/private_class_method_handler.rb +22 -22
  134. data/lib/yard/handlers/ruby/legacy/private_constant_handler.rb +22 -22
  135. data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +17 -17
  136. data/lib/yard/handlers/ruby/legacy/yield_handler.rb +29 -29
  137. data/lib/yard/handlers/ruby/method_condition_handler.rb +9 -9
  138. data/lib/yard/handlers/ruby/method_handler.rb +114 -118
  139. data/lib/yard/handlers/ruby/mixin_handler.rb +37 -37
  140. data/lib/yard/handlers/ruby/module_function_handler.rb +27 -27
  141. data/lib/yard/handlers/ruby/module_handler.rb +12 -12
  142. data/lib/yard/handlers/ruby/private_class_method_handler.rb +14 -14
  143. data/lib/yard/handlers/ruby/private_constant_handler.rb +43 -43
  144. data/lib/yard/handlers/ruby/public_class_method_handler.rb +14 -14
  145. data/lib/yard/handlers/ruby/struct_handler_methods.rb +143 -143
  146. data/lib/yard/handlers/ruby/visibility_handler.rb +22 -22
  147. data/lib/yard/handlers/ruby/yield_handler.rb +31 -31
  148. data/lib/yard/i18n/locale.rb +67 -67
  149. data/lib/yard/i18n/message.rb +57 -57
  150. data/lib/yard/i18n/messages.rb +56 -56
  151. data/lib/yard/i18n/po_parser.rb +61 -61
  152. data/lib/yard/i18n/pot_generator.rb +290 -290
  153. data/lib/yard/i18n/text.rb +173 -173
  154. data/lib/yard/logging.rb +205 -205
  155. data/lib/yard/options.rb +217 -217
  156. data/lib/yard/parser/base.rb +57 -57
  157. data/lib/yard/parser/c/c_parser.rb +235 -235
  158. data/lib/yard/parser/c/comment_parser.rb +134 -134
  159. data/lib/yard/parser/c/statement.rb +64 -64
  160. data/lib/yard/parser/ruby/ast_node.rb +540 -540
  161. data/lib/yard/parser/ruby/legacy/ruby_lex.rb +1354 -1354
  162. data/lib/yard/parser/ruby/legacy/ruby_parser.rb +32 -32
  163. data/lib/yard/parser/ruby/legacy/statement.rb +66 -66
  164. data/lib/yard/parser/ruby/legacy/statement_list.rb +394 -394
  165. data/lib/yard/parser/ruby/legacy/token_list.rb +74 -74
  166. data/lib/yard/parser/ruby/ruby_parser.rb +687 -687
  167. data/lib/yard/parser/ruby/token_resolver.rb +156 -156
  168. data/lib/yard/parser/source_parser.rb +526 -526
  169. data/lib/yard/rake/yardoc_task.rb +81 -81
  170. data/lib/yard/registry.rb +439 -439
  171. data/lib/yard/registry_resolver.rb +189 -189
  172. data/lib/yard/registry_store.rb +337 -337
  173. data/lib/yard/rubygems/backports.rb +10 -10
  174. data/lib/yard/rubygems/backports/LICENSE.txt +57 -57
  175. data/lib/yard/rubygems/backports/MIT.txt +20 -20
  176. data/lib/yard/rubygems/backports/gem.rb +10 -10
  177. data/lib/yard/rubygems/backports/source_index.rb +365 -365
  178. data/lib/yard/rubygems/doc_manager.rb +90 -90
  179. data/lib/yard/rubygems/hook.rb +197 -197
  180. data/lib/yard/rubygems/specification.rb +50 -50
  181. data/lib/yard/serializers/base.rb +83 -83
  182. data/lib/yard/serializers/file_system_serializer.rb +123 -123
  183. data/lib/yard/serializers/process_serializer.rb +24 -24
  184. data/lib/yard/serializers/stdout_serializer.rb +34 -34
  185. data/lib/yard/serializers/yardoc_serializer.rb +152 -152
  186. data/lib/yard/server.rb +13 -13
  187. data/lib/yard/server/adapter.rb +100 -100
  188. data/lib/yard/server/commands/base.rb +209 -209
  189. data/lib/yard/server/commands/display_file_command.rb +29 -29
  190. data/lib/yard/server/commands/display_object_command.rb +65 -65
  191. data/lib/yard/server/commands/frames_command.rb +16 -16
  192. data/lib/yard/server/commands/library_command.rb +187 -187
  193. data/lib/yard/server/commands/library_index_command.rb +28 -28
  194. data/lib/yard/server/commands/list_command.rb +25 -25
  195. data/lib/yard/server/commands/root_request_command.rb +15 -15
  196. data/lib/yard/server/commands/search_command.rb +79 -79
  197. data/lib/yard/server/commands/static_file_command.rb +23 -23
  198. data/lib/yard/server/commands/static_file_helpers.rb +62 -62
  199. data/lib/yard/server/doc_server_helper.rb +91 -91
  200. data/lib/yard/server/doc_server_serializer.rb +39 -39
  201. data/lib/yard/server/library_version.rb +277 -277
  202. data/lib/yard/server/rack_adapter.rb +89 -89
  203. data/lib/yard/server/router.rb +187 -187
  204. data/lib/yard/server/static_caching.rb +46 -46
  205. data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +127 -127
  206. data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +11 -11
  207. data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +37 -37
  208. data/lib/yard/server/templates/default/layout/html/script_setup.erb +7 -7
  209. data/lib/yard/server/templates/default/layout/html/setup.rb +8 -8
  210. data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -4
  211. data/lib/yard/server/templates/default/method_details/html/setup.rb +5 -5
  212. data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +8 -8
  213. data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +14 -14
  214. data/lib/yard/server/templates/doc_server/library_list/html/listing.erb +13 -13
  215. data/lib/yard/server/templates/doc_server/library_list/html/setup.rb +6 -6
  216. data/lib/yard/server/templates/doc_server/library_list/html/title.erb +2 -2
  217. data/lib/yard/server/templates/doc_server/processing/html/processing.erb +52 -52
  218. data/lib/yard/server/templates/doc_server/processing/html/setup.rb +4 -4
  219. data/lib/yard/server/templates/doc_server/search/html/search.erb +18 -18
  220. data/lib/yard/server/templates/doc_server/search/html/setup.rb +9 -9
  221. data/lib/yard/server/webrick_adapter.rb +45 -45
  222. data/lib/yard/tags/default_factory.rb +191 -191
  223. data/lib/yard/tags/default_tag.rb +13 -13
  224. data/lib/yard/tags/directives.rb +616 -616
  225. data/lib/yard/tags/library.rb +633 -633
  226. data/lib/yard/tags/option_tag.rb +13 -13
  227. data/lib/yard/tags/overload_tag.rb +71 -71
  228. data/lib/yard/tags/ref_tag.rb +8 -8
  229. data/lib/yard/tags/ref_tag_list.rb +28 -28
  230. data/lib/yard/tags/tag.rb +71 -71
  231. data/lib/yard/tags/tag_format_error.rb +7 -7
  232. data/lib/yard/tags/types_explainer.rb +162 -162
  233. data/lib/yard/templates/engine.rb +186 -186
  234. data/lib/yard/templates/erb_cache.rb +23 -23
  235. data/lib/yard/templates/helpers/base_helper.rb +215 -215
  236. data/lib/yard/templates/helpers/filter_helper.rb +27 -27
  237. data/lib/yard/templates/helpers/html_helper.rb +646 -646
  238. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +78 -78
  239. data/lib/yard/templates/helpers/markup/rdoc_markdown.rb +23 -23
  240. data/lib/yard/templates/helpers/markup/rdoc_markup.rb +109 -109
  241. data/lib/yard/templates/helpers/markup_helper.rb +172 -172
  242. data/lib/yard/templates/helpers/method_helper.rb +75 -75
  243. data/lib/yard/templates/helpers/module_helper.rb +21 -21
  244. data/lib/yard/templates/helpers/text_helper.rb +112 -112
  245. data/lib/yard/templates/helpers/uml_helper.rb +47 -47
  246. data/lib/yard/templates/section.rb +105 -105
  247. data/lib/yard/templates/template.rb +418 -418
  248. data/lib/yard/templates/template_options.rb +92 -92
  249. data/lib/yard/verifier.rb +151 -151
  250. data/lib/yard/version.rb +6 -6
  251. data/spec/cli/command_parser_spec.rb +43 -43
  252. data/spec/cli/command_spec.rb +36 -36
  253. data/spec/cli/config_spec.rb +148 -148
  254. data/spec/cli/diff_spec.rb +254 -254
  255. data/spec/cli/display_spec.rb +30 -30
  256. data/spec/cli/gems_spec.rb +81 -81
  257. data/spec/cli/graph_spec.rb +18 -18
  258. data/spec/cli/help_spec.rb +22 -22
  259. data/spec/cli/i18n_spec.rb +107 -107
  260. data/spec/cli/list_spec.rb +8 -8
  261. data/spec/cli/markup_types_spec.rb +22 -22
  262. data/spec/cli/server_spec.rb +324 -324
  263. data/spec/cli/stats_spec.rb +96 -96
  264. data/spec/cli/yard_on_yard_spec.rb +38 -38
  265. data/spec/cli/yardoc_spec.rb +896 -862
  266. data/spec/cli/yri_spec.rb +101 -101
  267. data/spec/code_objects/base_spec.rb +470 -470
  268. data/spec/code_objects/class_object_spec.rb +226 -226
  269. data/spec/code_objects/code_object_list_spec.rb +36 -36
  270. data/spec/code_objects/constants_spec.rb +116 -116
  271. data/spec/code_objects/extra_file_object_spec.rb +160 -160
  272. data/spec/code_objects/macro_object_spec.rb +150 -150
  273. data/spec/code_objects/method_object_spec.rb +184 -184
  274. data/spec/code_objects/module_object_spec.rb +142 -142
  275. data/spec/code_objects/namespace_object_spec.rb +171 -171
  276. data/spec/code_objects/proxy_spec.rb +141 -141
  277. data/spec/code_objects/spec_helper.rb +3 -3
  278. data/spec/config_spec.rb +171 -171
  279. data/spec/core_ext/array_spec.rb +13 -13
  280. data/spec/core_ext/file_spec.rb +72 -72
  281. data/spec/core_ext/hash_spec.rb +14 -14
  282. data/spec/core_ext/insertion_spec.rb +37 -37
  283. data/spec/core_ext/module_spec.rb +9 -15
  284. data/spec/core_ext/string_spec.rb +42 -42
  285. data/spec/core_ext/symbol_hash_spec.rb +89 -89
  286. data/spec/docstring_parser_spec.rb +280 -280
  287. data/spec/docstring_spec.rb +373 -373
  288. data/spec/examples.txt +1883 -1875
  289. data/spec/handlers/alias_handler_spec.rb +82 -82
  290. data/spec/handlers/attribute_handler_spec.rb +96 -96
  291. data/spec/handlers/base_spec.rb +216 -216
  292. data/spec/handlers/c/alias_handler_spec.rb +34 -34
  293. data/spec/handlers/c/attribute_handler_spec.rb +41 -41
  294. data/spec/handlers/c/class_handler_spec.rb +78 -78
  295. data/spec/handlers/c/constant_handler_spec.rb +71 -71
  296. data/spec/handlers/c/init_handler_spec.rb +48 -48
  297. data/spec/handlers/c/method_handler_spec.rb +327 -325
  298. data/spec/handlers/c/mixin_handler_spec.rb +44 -44
  299. data/spec/handlers/c/module_handler_spec.rb +71 -71
  300. data/spec/handlers/c/override_comment_handler_spec.rb +47 -47
  301. data/spec/handlers/c/path_handler_spec.rb +36 -36
  302. data/spec/handlers/c/spec_helper.rb +23 -23
  303. data/spec/handlers/c/struct_handler_spec.rb +16 -16
  304. data/spec/handlers/class_condition_handler_spec.rb +87 -87
  305. data/spec/handlers/class_handler_spec.rb +247 -247
  306. data/spec/handlers/class_method_handler_shared_examples.rb +133 -133
  307. data/spec/handlers/class_variable_handler_spec.rb +12 -12
  308. data/spec/handlers/constant_handler_spec.rb +112 -112
  309. data/spec/handlers/decorator_handler_methods_spec.rb +393 -393
  310. data/spec/handlers/dsl_handler_spec.rb +219 -219
  311. data/spec/handlers/examples/alias_handler_001.rb.txt +45 -45
  312. data/spec/handlers/examples/attribute_handler_001.rb.txt +31 -31
  313. data/spec/handlers/examples/class_condition_handler_001.rb.txt +68 -68
  314. data/spec/handlers/examples/class_handler_001.rb.txt +120 -120
  315. data/spec/handlers/examples/class_variable_handler_001.rb.txt +9 -9
  316. data/spec/handlers/examples/constant_handler_001.rb.txt +35 -35
  317. data/spec/handlers/examples/dsl_handler_001.rb.txt +154 -154
  318. data/spec/handlers/examples/exception_handler_001.rb.txt +58 -58
  319. data/spec/handlers/examples/extend_handler_001.rb.txt +15 -15
  320. data/spec/handlers/examples/method_condition_handler_001.rb.txt +9 -9
  321. data/spec/handlers/examples/method_handler_001.rb.txt +128 -128
  322. data/spec/handlers/examples/mixin_handler_001.rb.txt +37 -37
  323. data/spec/handlers/examples/module_handler_001.rb.txt +29 -29
  324. data/spec/handlers/examples/private_constant_handler_001.rb.txt +8 -8
  325. data/spec/handlers/examples/process_handler_001.rb.txt +11 -11
  326. data/spec/handlers/examples/visibility_handler_001.rb.txt +35 -35
  327. data/spec/handlers/examples/yield_handler_001.rb.txt +54 -54
  328. data/spec/handlers/exception_handler_spec.rb +49 -49
  329. data/spec/handlers/extend_handler_spec.rb +24 -24
  330. data/spec/handlers/legacy_base_spec.rb +128 -128
  331. data/spec/handlers/method_condition_handler_spec.rb +15 -15
  332. data/spec/handlers/method_handler_spec.rb +190 -190
  333. data/spec/handlers/mixin_handler_spec.rb +56 -56
  334. data/spec/handlers/module_function_handler_spec.rb +106 -106
  335. data/spec/handlers/module_handler_spec.rb +35 -35
  336. data/spec/handlers/private_class_method_handler_spec.rb +11 -11
  337. data/spec/handlers/private_constant_handler_spec.rb +25 -25
  338. data/spec/handlers/processor_spec.rb +35 -35
  339. data/spec/handlers/public_class_method_handler_spec.rb +11 -11
  340. data/spec/handlers/ruby/base_spec.rb +95 -95
  341. data/spec/handlers/ruby/legacy/base_spec.rb +84 -84
  342. data/spec/handlers/spec_helper.rb +33 -33
  343. data/spec/handlers/visibility_handler_spec.rb +44 -44
  344. data/spec/handlers/yield_handler_spec.rb +52 -52
  345. data/spec/i18n/locale_spec.rb +81 -81
  346. data/spec/i18n/message_spec.rb +52 -52
  347. data/spec/i18n/messages_spec.rb +67 -67
  348. data/spec/i18n/pot_generator_spec.rb +295 -295
  349. data/spec/i18n/text_spec.rb +184 -184
  350. data/spec/logging_spec.rb +44 -44
  351. data/spec/options_spec.rb +171 -171
  352. data/spec/parser/base_spec.rb +24 -24
  353. data/spec/parser/c_parser_spec.rb +236 -236
  354. data/spec/parser/examples/array.c.txt +6267 -6267
  355. data/spec/parser/examples/example1.rb.txt +7 -7
  356. data/spec/parser/examples/extrafile.c.txt +8 -8
  357. data/spec/parser/examples/file.c.txt +28 -28
  358. data/spec/parser/examples/multifile.c.txt +22 -22
  359. data/spec/parser/examples/namespace.cpp.txt +68 -68
  360. data/spec/parser/examples/override.c.txt +424 -424
  361. data/spec/parser/examples/parse_in_order_001.rb.txt +2 -2
  362. data/spec/parser/examples/parse_in_order_002.rb.txt +1 -1
  363. data/spec/parser/examples/tag_handler_001.rb.txt +7 -7
  364. data/spec/parser/ruby/ast_node_spec.rb +33 -33
  365. data/spec/parser/ruby/legacy/statement_list_spec.rb +299 -299
  366. data/spec/parser/ruby/legacy/token_list_spec.rb +79 -79
  367. data/spec/parser/ruby/ruby_parser_spec.rb +508 -508
  368. data/spec/parser/ruby/token_resolver_spec.rb +165 -165
  369. data/spec/parser/source_parser_spec.rb +727 -727
  370. data/spec/parser/tag_parsing_spec.rb +17 -17
  371. data/spec/rake/yardoc_task_spec.rb +118 -118
  372. data/spec/registry_spec.rb +463 -463
  373. data/spec/registry_store_spec.rb +316 -316
  374. data/spec/rubygems/doc_manager_spec.rb +112 -112
  375. data/spec/serializers/data/serialized_yardoc/checksums +1 -1
  376. data/spec/serializers/file_system_serializer_spec.rb +145 -145
  377. data/spec/serializers/spec_helper.rb +2 -2
  378. data/spec/serializers/yardoc_serializer_spec.rb +78 -78
  379. data/spec/server/adapter_spec.rb +39 -39
  380. data/spec/server/commands/base_spec.rb +91 -91
  381. data/spec/server/commands/library_command_spec.rb +39 -39
  382. data/spec/server/doc_server_helper_spec.rb +72 -72
  383. data/spec/server/doc_server_serializer_spec.rb +60 -60
  384. data/spec/server/rack_adapter_spec.rb +21 -21
  385. data/spec/server/router_spec.rb +123 -123
  386. data/spec/server/spec_helper.rb +22 -22
  387. data/spec/server/static_caching_spec.rb +47 -47
  388. data/spec/server/webrick_servlet_spec.rb +20 -20
  389. data/spec/server_spec.rb +19 -19
  390. data/spec/spec_helper.rb +212 -212
  391. data/spec/tags/default_factory_spec.rb +168 -168
  392. data/spec/tags/default_tag_spec.rb +11 -11
  393. data/spec/tags/directives_spec.rb +463 -463
  394. data/spec/tags/library_spec.rb +48 -48
  395. data/spec/tags/overload_tag_spec.rb +53 -53
  396. data/spec/tags/ref_tag_list_spec.rb +53 -53
  397. data/spec/tags/types_explainer_spec.rb +203 -203
  398. data/spec/templates/class_spec.rb +45 -45
  399. data/spec/templates/constant_spec.rb +41 -41
  400. data/spec/templates/engine_spec.rb +131 -131
  401. data/spec/templates/examples/class001.html +308 -308
  402. data/spec/templates/examples/class001.txt +36 -36
  403. data/spec/templates/examples/class002.html +39 -39
  404. data/spec/templates/examples/constant001.txt +24 -24
  405. data/spec/templates/examples/constant002.txt +6 -6
  406. data/spec/templates/examples/constant003.txt +10 -10
  407. data/spec/templates/examples/method001.html +137 -137
  408. data/spec/templates/examples/method001.txt +35 -35
  409. data/spec/templates/examples/method002.html +91 -91
  410. data/spec/templates/examples/method002.txt +20 -20
  411. data/spec/templates/examples/method003.html +165 -165
  412. data/spec/templates/examples/method003.txt +45 -45
  413. data/spec/templates/examples/method004.html +48 -48
  414. data/spec/templates/examples/method004.txt +10 -10
  415. data/spec/templates/examples/method005.html +105 -105
  416. data/spec/templates/examples/method005.txt +33 -33
  417. data/spec/templates/examples/method006.html +107 -107
  418. data/spec/templates/examples/method006.txt +20 -20
  419. data/spec/templates/examples/module001.dot +33 -33
  420. data/spec/templates/examples/module001.html +833 -833
  421. data/spec/templates/examples/module001.txt +33 -33
  422. data/spec/templates/examples/module002.html +341 -341
  423. data/spec/templates/examples/module003.html +202 -202
  424. data/spec/templates/examples/module004.html +394 -394
  425. data/spec/templates/examples/module005.html +81 -81
  426. data/spec/templates/examples/tag001.txt +82 -82
  427. data/spec/templates/helpers/base_helper_spec.rb +171 -171
  428. data/spec/templates/helpers/html_helper_spec.rb +687 -668
  429. data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +65 -65
  430. data/spec/templates/helpers/markup/rdoc_markup_spec.rb +84 -84
  431. data/spec/templates/helpers/markup_helper_spec.rb +136 -136
  432. data/spec/templates/helpers/method_helper_spec.rb +107 -107
  433. data/spec/templates/helpers/module_helper_spec.rb +35 -35
  434. data/spec/templates/helpers/shared_signature_examples.rb +126 -126
  435. data/spec/templates/helpers/text_helper_spec.rb +65 -65
  436. data/spec/templates/method_spec.rb +118 -118
  437. data/spec/templates/module_spec.rb +203 -203
  438. data/spec/templates/onefile_spec.rb +66 -66
  439. data/spec/templates/section_spec.rb +144 -144
  440. data/spec/templates/spec_helper.rb +76 -76
  441. data/spec/templates/tag_spec.rb +52 -52
  442. data/spec/templates/template_spec.rb +410 -410
  443. data/spec/verifier_spec.rb +106 -106
  444. data/templates/default/class/dot/setup.rb +7 -7
  445. data/templates/default/class/dot/superklass.erb +2 -2
  446. data/templates/default/class/html/constructor_details.erb +8 -8
  447. data/templates/default/class/html/setup.rb +2 -2
  448. data/templates/default/class/html/subclasses.erb +4 -4
  449. data/templates/default/class/setup.rb +36 -36
  450. data/templates/default/class/text/setup.rb +12 -12
  451. data/templates/default/class/text/subclasses.erb +5 -5
  452. data/templates/default/constant/text/header.erb +11 -11
  453. data/templates/default/constant/text/setup.rb +4 -4
  454. data/templates/default/docstring/html/abstract.erb +4 -4
  455. data/templates/default/docstring/html/deprecated.erb +1 -1
  456. data/templates/default/docstring/html/index.erb +5 -5
  457. data/templates/default/docstring/html/note.erb +6 -6
  458. data/templates/default/docstring/html/private.erb +4 -4
  459. data/templates/default/docstring/html/text.erb +1 -1
  460. data/templates/default/docstring/html/todo.erb +6 -6
  461. data/templates/default/docstring/setup.rb +52 -52
  462. data/templates/default/docstring/text/abstract.erb +2 -2
  463. data/templates/default/docstring/text/deprecated.erb +2 -2
  464. data/templates/default/docstring/text/index.erb +2 -2
  465. data/templates/default/docstring/text/note.erb +3 -3
  466. data/templates/default/docstring/text/private.erb +2 -2
  467. data/templates/default/docstring/text/text.erb +1 -1
  468. data/templates/default/docstring/text/todo.erb +3 -3
  469. data/templates/default/fulldoc/html/css/full_list.css +58 -58
  470. data/templates/default/fulldoc/html/css/style.css +496 -496
  471. data/templates/default/fulldoc/html/frames.erb +17 -17
  472. data/templates/default/fulldoc/html/full_list.erb +37 -37
  473. data/templates/default/fulldoc/html/full_list_class.erb +2 -2
  474. data/templates/default/fulldoc/html/full_list_file.erb +7 -7
  475. data/templates/default/fulldoc/html/full_list_method.erb +10 -10
  476. data/templates/default/fulldoc/html/js/app.js +303 -292
  477. data/templates/default/fulldoc/html/js/full_list.js +216 -216
  478. data/templates/default/fulldoc/html/js/jquery.js +3 -3
  479. data/templates/default/fulldoc/html/setup.rb +241 -241
  480. data/templates/default/layout/dot/header.erb +5 -5
  481. data/templates/default/layout/dot/setup.rb +15 -15
  482. data/templates/default/layout/html/breadcrumb.erb +11 -11
  483. data/templates/default/layout/html/files.erb +11 -11
  484. data/templates/default/layout/html/footer.erb +5 -5
  485. data/templates/default/layout/html/headers.erb +15 -15
  486. data/templates/default/layout/html/index.erb +2 -2
  487. data/templates/default/layout/html/layout.erb +23 -23
  488. data/templates/default/layout/html/listing.erb +4 -4
  489. data/templates/default/layout/html/objects.erb +32 -32
  490. data/templates/default/layout/html/script_setup.erb +4 -4
  491. data/templates/default/layout/html/search.erb +12 -12
  492. data/templates/default/layout/html/setup.rb +89 -89
  493. data/templates/default/method/html/header.erb +16 -16
  494. data/templates/default/method/setup.rb +4 -4
  495. data/templates/default/method_details/html/header.erb +2 -2
  496. data/templates/default/method_details/html/method_signature.erb +24 -24
  497. data/templates/default/method_details/html/source.erb +9 -9
  498. data/templates/default/method_details/setup.rb +11 -11
  499. data/templates/default/method_details/text/header.erb +10 -10
  500. data/templates/default/method_details/text/method_signature.erb +12 -12
  501. data/templates/default/method_details/text/setup.rb +11 -11
  502. data/templates/default/module/dot/child.erb +1 -1
  503. data/templates/default/module/dot/dependencies.erb +2 -2
  504. data/templates/default/module/dot/header.erb +6 -6
  505. data/templates/default/module/dot/info.erb +13 -13
  506. data/templates/default/module/dot/setup.rb +15 -15
  507. data/templates/default/module/html/attribute_details.erb +10 -10
  508. data/templates/default/module/html/attribute_summary.erb +8 -8
  509. data/templates/default/module/html/box_info.erb +43 -43
  510. data/templates/default/module/html/children.erb +8 -8
  511. data/templates/default/module/html/constant_summary.erb +17 -17
  512. data/templates/default/module/html/defines.erb +2 -2
  513. data/templates/default/module/html/header.erb +5 -5
  514. data/templates/default/module/html/inherited_attributes.erb +14 -14
  515. data/templates/default/module/html/inherited_constants.erb +8 -8
  516. data/templates/default/module/html/inherited_methods.erb +18 -18
  517. data/templates/default/module/html/item_summary.erb +40 -40
  518. data/templates/default/module/html/method_details_list.erb +9 -9
  519. data/templates/default/module/html/method_summary.erb +13 -13
  520. data/templates/default/module/html/methodmissing.erb +12 -12
  521. data/templates/default/module/setup.rb +167 -167
  522. data/templates/default/module/text/children.erb +9 -9
  523. data/templates/default/module/text/class_meths_list.erb +7 -7
  524. data/templates/default/module/text/extends.erb +7 -7
  525. data/templates/default/module/text/header.erb +7 -7
  526. data/templates/default/module/text/includes.erb +7 -7
  527. data/templates/default/module/text/instance_meths_list.erb +7 -7
  528. data/templates/default/module/text/setup.rb +13 -13
  529. data/templates/default/onefile/html/files.erb +4 -4
  530. data/templates/default/onefile/html/headers.erb +6 -6
  531. data/templates/default/onefile/html/layout.erb +17 -17
  532. data/templates/default/onefile/html/readme.erb +2 -2
  533. data/templates/default/onefile/html/setup.rb +62 -62
  534. data/templates/default/root/dot/child.erb +2 -2
  535. data/templates/default/root/dot/setup.rb +6 -6
  536. data/templates/default/root/html/setup.rb +2 -2
  537. data/templates/default/tags/html/example.erb +10 -10
  538. data/templates/default/tags/html/index.erb +2 -2
  539. data/templates/default/tags/html/option.erb +24 -24
  540. data/templates/default/tags/html/overload.erb +13 -13
  541. data/templates/default/tags/html/see.erb +7 -7
  542. data/templates/default/tags/html/tag.erb +20 -20
  543. data/templates/default/tags/setup.rb +57 -57
  544. data/templates/default/tags/text/example.erb +12 -12
  545. data/templates/default/tags/text/index.erb +1 -1
  546. data/templates/default/tags/text/option.erb +20 -20
  547. data/templates/default/tags/text/overload.erb +19 -19
  548. data/templates/default/tags/text/see.erb +11 -11
  549. data/templates/default/tags/text/tag.erb +13 -13
  550. data/templates/guide/class/html/setup.rb +2 -2
  551. data/templates/guide/docstring/html/setup.rb +2 -2
  552. data/templates/guide/fulldoc/html/css/style.css +108 -108
  553. data/templates/guide/fulldoc/html/js/app.js +33 -33
  554. data/templates/guide/fulldoc/html/setup.rb +74 -74
  555. data/templates/guide/layout/html/layout.erb +81 -81
  556. data/templates/guide/layout/html/setup.rb +25 -25
  557. data/templates/guide/method/html/header.erb +17 -17
  558. data/templates/guide/method/html/setup.rb +22 -22
  559. data/templates/guide/module/html/header.erb +6 -6
  560. data/templates/guide/module/html/method_list.erb +4 -4
  561. data/templates/guide/module/html/setup.rb +27 -27
  562. data/templates/guide/onefile/html/files.erb +4 -4
  563. data/templates/guide/onefile/html/setup.rb +6 -6
  564. data/templates/guide/onefile/html/toc.erb +3 -3
  565. data/templates/guide/tags/html/setup.rb +9 -9
  566. data/yard.gemspec +43 -43
  567. metadata +4 -3
@@ -1,156 +1,156 @@
1
- # frozen_string_literal: true
2
- module YARD
3
- module Parser
4
- module Ruby
5
- # Supports {#each} enumeration over a source's tokens, yielding
6
- # the token and a possible {CodeObjects::Base} associated with the
7
- # constant or identifier token.
8
- class TokenResolver
9
- include Enumerable
10
-
11
- # Creates a token resolver for given source.
12
- #
13
- # @param source [String] the source code to tokenize
14
- # @param namespace [CodeObjects::Base] the object/namespace to resolve from
15
- def initialize(source, namespace = Registry.root)
16
- @tokens = RubyParser.parse(source, '(tokenize)').tokens
17
- raise ParserSyntaxError if @tokens.empty? && !source.empty?
18
- @default_namespace = namespace
19
- end
20
-
21
- # Iterates over each token, yielding the token and a possible code
22
- # object that is associated with the token.
23
- #
24
- # @yieldparam token [Array(Symbol,String,Array(Integer,Integer))] the
25
- # current token object being iterated
26
- # @yieldparam object [CodeObjects::Base, nil] the fully qualified code
27
- # object associated with the current token, or nil if there is no object
28
- # for the yielded token.
29
- # @example Yielding code objects
30
- # r = TokenResolver.new("A::B::C")
31
- # r.each do |tok, obj|
32
- # if obj
33
- # puts "#{tok[0]} -> #{obj.path.inspect}"
34
- # else
35
- # puts "No object: #{tok.inspect}"
36
- # end
37
- # end
38
- #
39
- # # Prints:
40
- # # :const -> "A"
41
- # # No object: [:op, "::"]
42
- # # :const -> "A::B"
43
- # # No object: [:op, "::"]
44
- # # :const -> "A::B::C"
45
- def each
46
- @states = []
47
- push_state
48
- @tokens.each do |token|
49
- yield_obj = false
50
-
51
- if skip_group && [:const, :ident, :op, :period].include?(token[0])
52
- yield token, nil
53
- next
54
- else
55
- self.skip_group = false
56
- end
57
-
58
- case token[0]
59
- when :const
60
- lookup(token[0], token[1])
61
- yield_obj = true
62
- self.last_sep = nil
63
- when :ident
64
- lookup(token[0], token[1])
65
- yield_obj = true
66
- self.last_sep = nil
67
- when :op, :period
68
- self.last_sep = token[1]
69
- unless CodeObjects.types_for_separator(token[1])
70
- self.object = nil
71
- self.last_sep = nil
72
- end
73
- when :lparen
74
- push_state
75
- when :rparen
76
- pop_state
77
- else
78
- self.object = nil
79
- end
80
-
81
- yield token, (yield_obj ? object : nil)
82
-
83
- if next_object
84
- self.object = next_object
85
- self.next_object = nil
86
- end
87
- self.skip_group = true if yield_obj && object.nil?
88
- end
89
- end
90
-
91
- def self.state_attr(*attrs)
92
- attrs.each do |attr|
93
- define_method(attr) { @states.last[attr.to_sym] }
94
- define_method("#{attr}=") {|v| @states.last[attr.to_sym] = v }
95
- protected attr, :"#{attr}="
96
- end
97
- end
98
-
99
- private
100
-
101
- def push_state
102
- @states.push :object => nil, :skip_group => false, :last_sep => nil
103
- end
104
-
105
- def pop_state
106
- @states.pop
107
- end
108
-
109
- state_attr :object, :next_object, :skip_group, :last_sep
110
-
111
- def lookup(toktype, name)
112
- types = object_resolved_types
113
- return self.object = nil if types.empty?
114
-
115
- if toktype == :const
116
- types.any? do |type|
117
- prefix = (type ? type.path : "") + last_sep.to_s
118
- self.object = Registry.resolve(@default_namespace, "#{prefix}#{name}", true)
119
- end
120
- else # ident
121
- types.any? do |type|
122
- obj = Registry.resolve(type, name, true)
123
- if obj.nil? && name == "new"
124
- obj = Registry.resolve(object, "#initialize", true)
125
- self.next_object = object if obj.nil?
126
- end
127
- self.object = obj
128
- end
129
- end
130
- end
131
-
132
- def object_resolved_types(obj = object)
133
- return [obj] unless obj.is_a?(CodeObjects::MethodObject)
134
-
135
- resolved_types = []
136
- tags = obj.tags(:return)
137
- tags += obj.tags(:overload).map {|o| o.tags(:return) }.flatten
138
- tags.each do |tag|
139
- next if tag.types.nil?
140
- tag.types.each do |type|
141
- type = type.sub(/<.+>/, '')
142
- if type == "self"
143
- resolved_types << obj.parent
144
- else
145
- type_obj = Registry.resolve(obj, type, true)
146
- resolved_types << type_obj if type_obj
147
- end
148
- end
149
- end
150
-
151
- resolved_types
152
- end
153
- end
154
- end
155
- end
156
- end
1
+ # frozen_string_literal: true
2
+ module YARD
3
+ module Parser
4
+ module Ruby
5
+ # Supports {#each} enumeration over a source's tokens, yielding
6
+ # the token and a possible {CodeObjects::Base} associated with the
7
+ # constant or identifier token.
8
+ class TokenResolver
9
+ include Enumerable
10
+
11
+ # Creates a token resolver for given source.
12
+ #
13
+ # @param source [String] the source code to tokenize
14
+ # @param namespace [CodeObjects::Base] the object/namespace to resolve from
15
+ def initialize(source, namespace = Registry.root)
16
+ @tokens = RubyParser.parse(source, '(tokenize)').tokens
17
+ raise ParserSyntaxError if @tokens.empty? && !source.empty?
18
+ @default_namespace = namespace
19
+ end
20
+
21
+ # Iterates over each token, yielding the token and a possible code
22
+ # object that is associated with the token.
23
+ #
24
+ # @yieldparam token [Array(Symbol,String,Array(Integer,Integer))] the
25
+ # current token object being iterated
26
+ # @yieldparam object [CodeObjects::Base, nil] the fully qualified code
27
+ # object associated with the current token, or nil if there is no object
28
+ # for the yielded token.
29
+ # @example Yielding code objects
30
+ # r = TokenResolver.new("A::B::C")
31
+ # r.each do |tok, obj|
32
+ # if obj
33
+ # puts "#{tok[0]} -> #{obj.path.inspect}"
34
+ # else
35
+ # puts "No object: #{tok.inspect}"
36
+ # end
37
+ # end
38
+ #
39
+ # # Prints:
40
+ # # :const -> "A"
41
+ # # No object: [:op, "::"]
42
+ # # :const -> "A::B"
43
+ # # No object: [:op, "::"]
44
+ # # :const -> "A::B::C"
45
+ def each
46
+ @states = []
47
+ push_state
48
+ @tokens.each do |token|
49
+ yield_obj = false
50
+
51
+ if skip_group && [:const, :ident, :op, :period].include?(token[0])
52
+ yield token, nil
53
+ next
54
+ else
55
+ self.skip_group = false
56
+ end
57
+
58
+ case token[0]
59
+ when :const
60
+ lookup(token[0], token[1])
61
+ yield_obj = true
62
+ self.last_sep = nil
63
+ when :ident
64
+ lookup(token[0], token[1])
65
+ yield_obj = true
66
+ self.last_sep = nil
67
+ when :op, :period
68
+ self.last_sep = token[1]
69
+ unless CodeObjects.types_for_separator(token[1])
70
+ self.object = nil
71
+ self.last_sep = nil
72
+ end
73
+ when :lparen
74
+ push_state
75
+ when :rparen
76
+ pop_state
77
+ else
78
+ self.object = nil
79
+ end
80
+
81
+ yield token, (yield_obj ? object : nil)
82
+
83
+ if next_object
84
+ self.object = next_object
85
+ self.next_object = nil
86
+ end
87
+ self.skip_group = true if yield_obj && object.nil?
88
+ end
89
+ end
90
+
91
+ def self.state_attr(*attrs)
92
+ attrs.each do |attr|
93
+ define_method(attr) { @states.last[attr.to_sym] }
94
+ define_method("#{attr}=") {|v| @states.last[attr.to_sym] = v }
95
+ protected attr, :"#{attr}="
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def push_state
102
+ @states.push :object => nil, :skip_group => false, :last_sep => nil
103
+ end
104
+
105
+ def pop_state
106
+ @states.pop
107
+ end
108
+
109
+ state_attr :object, :next_object, :skip_group, :last_sep
110
+
111
+ def lookup(toktype, name)
112
+ types = object_resolved_types
113
+ return self.object = nil if types.empty?
114
+
115
+ if toktype == :const
116
+ types.any? do |type|
117
+ prefix = (type ? type.path : "") + last_sep.to_s
118
+ self.object = Registry.resolve(@default_namespace, "#{prefix}#{name}", true)
119
+ end
120
+ else # ident
121
+ types.any? do |type|
122
+ obj = Registry.resolve(type, name, true)
123
+ if obj.nil? && name == "new"
124
+ obj = Registry.resolve(object, "#initialize", true)
125
+ self.next_object = object if obj.nil?
126
+ end
127
+ self.object = obj
128
+ end
129
+ end
130
+ end
131
+
132
+ def object_resolved_types(obj = object)
133
+ return [obj] unless obj.is_a?(CodeObjects::MethodObject)
134
+
135
+ resolved_types = []
136
+ tags = obj.tags(:return)
137
+ tags += obj.tags(:overload).map {|o| o.tags(:return) }.flatten
138
+ tags.each do |tag|
139
+ next if tag.types.nil?
140
+ tag.types.each do |type|
141
+ type = type.sub(/<.+>/, '')
142
+ if type == "self"
143
+ resolved_types << obj.parent
144
+ else
145
+ type_obj = Registry.resolve(obj, type, true)
146
+ resolved_types << type_obj if type_obj
147
+ end
148
+ end
149
+ end
150
+
151
+ resolved_types
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -1,526 +1,526 @@
1
- # frozen_string_literal: true
2
- require 'stringio'
3
- require 'ostruct'
4
-
5
- module YARD
6
- module Parser
7
- # Raised when an object is recognized but cannot be documented. This
8
- # generally occurs when the Ruby syntax used to declare an object is
9
- # too dynamic in nature.
10
- class UndocumentableError < RuntimeError; end
11
-
12
- # Raised when the parser sees a Ruby syntax error
13
- class ParserSyntaxError < UndocumentableError; end
14
-
15
- # Responsible for parsing a list of files in order. The
16
- # {#parse} method of this class can be called from the
17
- # {SourceParser#globals} globals state list to re-enter
18
- # parsing for the remainder of files in the list recursively.
19
- #
20
- # @see Processor#parse_remaining_files
21
- class OrderedParser
22
- # @return [Array<String>] the list of remaining files to parse
23
- attr_accessor :files
24
-
25
- # Creates a new OrderedParser with the global state and a list
26
- # of files to parse.
27
- #
28
- # @note OrderedParser sets itself as the +ordered_parser+ key on
29
- # global_state for later use in {Handlers::Processor}.
30
- # @param [OpenStruct] global_state a structure containing all global
31
- # state during parsing
32
- # @param [Array<String>] files the list of files to parse
33
- def initialize(global_state, files)
34
- @global_state = global_state
35
- @files = files.dup
36
- @global_state.ordered_parser = self
37
- end
38
-
39
- # Parses the remainder of the {#files} list.
40
- #
41
- # @see Processor#parse_remaining_files
42
- def parse
43
- until files.empty?
44
- file = files.shift
45
- log.capture("Parsing #{file}") do
46
- SourceParser.new(SourceParser.parser_type, @global_state).parse(file)
47
- end
48
- end
49
- end
50
- end
51
-
52
- # Responsible for parsing a source file into the namespace. Parsing
53
- # also invokes handlers to process the parsed statements and generate
54
- # any code objects that may be recognized.
55
- #
56
- # == Custom Parsers
57
- # SourceParser allows custom parsers to be registered and called when
58
- # a certain filetype is recognized. To register a parser and hook it
59
- # up to a set of file extensions, call {register_parser_type}
60
- #
61
- # @see register_parser_type
62
- # @see Handlers::Base
63
- # @see CodeObjects::Base
64
- class SourceParser
65
- SHEBANG_LINE = /\A\s*#!\S+/
66
- ENCODING_LINE = %r{\A(?:\s*#*!.*\r?\n)?\s*(?:#+|/\*+|//+).*coding\s*[:=]{1,2}\s*([a-z\d_\-]+)}i
67
- FROZEN_STRING_LINE = /frozen(-|_)string(-|_)literal: true/i
68
-
69
- # The default glob of files to be parsed.
70
- # @since 0.9.0
71
- DEFAULT_PATH_GLOB = ["{lib,app}/**/*.rb", "ext/**/*.{c,cc,cxx,cpp,rb}"]
72
-
73
- # Byte order marks for various encodings
74
- # @since 0.7.0
75
- ENCODING_BYTE_ORDER_MARKS = {
76
- 'utf-8' => String.new("\xEF\xBB\xBF"),
77
- # Not yet supported
78
- # 'utf-16be' => "\xFE\xFF",
79
- # 'utf-16le' => "\xFF\xFE",
80
- # 'utf-32be' => "\x00\x00\xFF\xFE",
81
- # 'utf-32le' => "\xFF\xFE",
82
- }
83
-
84
- class << self
85
- # @return [Symbol] the default parser type (defaults to :ruby)
86
- attr_reader :parser_type
87
-
88
- def parser_type=(value)
89
- @parser_type = validated_parser_type(value)
90
- end
91
-
92
- # Parses a path or set of paths
93
- #
94
- # @param [String, Array<String>] paths a path, glob, or list of paths to
95
- # parse
96
- # @param [Array<String, Regexp>] excluded a list of excluded path matchers
97
- # @param [Fixnum] level the logger level to use during parsing. See
98
- # {YARD::Logger}
99
- # @return [void]
100
- def parse(paths = DEFAULT_PATH_GLOB, excluded = [], level = log.level)
101
- log.debug("Parsing #{paths.inspect} with `#{parser_type}` parser")
102
- excluded = excluded.map do |path|
103
- case path
104
- when Regexp; path
105
- else Regexp.new(path.to_s, Regexp::IGNORECASE)
106
- end
107
- end
108
- files = [paths].flatten.
109
- map {|p| File.directory?(p) ? "#{p}/**/*.{rb,c,cc,cxx,cpp}" : p }.
110
- map {|p| p.include?("*") ? Dir[p].sort_by {|d| [d.length, d] } : p }.flatten.
111
- reject {|p| !File.file?(p) || excluded.any? {|re| p =~ re } }
112
-
113
- log.enter_level(level) do
114
- parse_in_order(*files.uniq)
115
- end
116
- end
117
-
118
- # Parses a string +content+
119
- #
120
- # @param [String] content the block of code to parse
121
- # @param [Symbol] ptype the parser type to use. See {parser_type}.
122
- # @return the parser object that was used to parse +content+
123
- def parse_string(content, ptype = parser_type)
124
- new(ptype).parse(StringIO.new(content))
125
- end
126
-
127
- # Tokenizes but does not parse the block of code
128
- #
129
- # @param [String] content the block of code to tokenize
130
- # @param [Symbol] ptype the parser type to use. See {parser_type}.
131
- # @return [Array] a list of tokens
132
- def tokenize(content, ptype = parser_type)
133
- new(ptype).tokenize(content)
134
- end
135
-
136
- # Registers a new parser type.
137
- #
138
- # @example Registering a parser for "java" files
139
- # SourceParser.register_parser_type :java, JavaParser, 'java'
140
- # @param [Symbol] type a symbolic name for the parser type
141
- # @param [Base] parser_klass a class that implements parsing and tokenization
142
- # @param [Array<String>, String, Regexp] extensions a list of extensions or a
143
- # regex to match against the file extension
144
- # @return [void]
145
- # @see Parser::Base
146
- def register_parser_type(type, parser_klass, extensions = nil)
147
- unless Base > parser_klass
148
- raise ArgumentError, "expecting parser_klass to be a subclass of YARD::Parser::Base"
149
- end
150
- parser_type_extensions[type.to_sym] = extensions if extensions
151
- parser_types[type.to_sym] = parser_klass
152
- end
153
-
154
- # @return [Hash{Symbol=>Object}] a list of registered parser types
155
- # @private
156
- # @since 0.5.6
157
- def parser_types; @@parser_types ||= {} end
158
- def parser_types=(value) @@parser_types = value end
159
-
160
- # @return [Hash] a list of registered parser type extensions
161
- # @private
162
- # @since 0.5.6
163
- def parser_type_extensions; @@parser_type_extensions ||= {} end
164
- def parser_type_extensions=(value) @@parser_type_extensions = value end
165
-
166
- # Finds a parser type that is registered for the extension. If no
167
- # type is found, the default Ruby type is returned.
168
- #
169
- # @return [Symbol] the parser type to be used for the extension
170
- # @since 0.5.6
171
- def parser_type_for_extension(extension)
172
- type = parser_type_extensions.find do |_t, exts|
173
- [exts].flatten.any? {|ext| ext === extension }
174
- end
175
- validated_parser_type(type ? type.first : :ruby)
176
- end
177
-
178
- # Returns the validated parser type. Basically, enforces that :ruby
179
- # type is never set if the Ripper library is not available
180
- #
181
- # @param [Symbol] type the parser type to set
182
- # @return [Symbol] the validated parser type
183
- # @private
184
- def validated_parser_type(type)
185
- !defined?(::Ripper) && type == :ruby ? :ruby18 : type
186
- end
187
-
188
- # @group Parser Callbacks
189
-
190
- # Registers a callback to be called before a list of files is parsed
191
- # via {parse}. The block passed to this method will be called on
192
- # subsequent parse calls.
193
- #
194
- # @example Installing a simple callback
195
- # SourceParser.before_parse_list do |files, globals|
196
- # puts "Starting to parse..."
197
- # end
198
- # YARD.parse('lib/**/*.rb')
199
- # # prints "Starting to parse..."
200
- #
201
- # @example Setting global state
202
- # SourceParser.before_parse_list do |files, globals|
203
- # globals.method_count = 0
204
- # end
205
- # SourceParser.after_parse_list do |files, globals|
206
- # puts "Found #{globals.method_count} methods"
207
- # end
208
- # class MyCountHandler < Handlers::Ruby::Base
209
- # handles :def, :defs
210
- # process { globals.method_count += 1 }
211
- # end
212
- # YARD.parse
213
- # # Prints: "Found 37 methods"
214
- #
215
- # @example Using a global callback to cancel parsing
216
- # SourceParser.before_parse_list do |files, globals|
217
- # return false if files.include?('foo.rb')
218
- # end
219
- #
220
- # YARD.parse(['foo.rb', 'bar.rb']) # callback cancels this method
221
- # YARD.parse('bar.rb') # parses normally
222
- #
223
- # @yield [files, globals] the yielded block is called once before
224
- # parsing all files
225
- # @yieldparam [Array<String>] files the list of files that will be parsed.
226
- # @yieldparam [OpenStruct] globals a global structure to store arbitrary
227
- # state for post processing (see {Handlers::Processor#globals})
228
- # @yieldreturn [Boolean] if the block returns +false+, parsing is
229
- # cancelled.
230
- # @return [Proc] the yielded block
231
- # @see after_parse_list
232
- # @see before_parse_file
233
- # @since 0.7.0
234
- def before_parse_list(&block)
235
- before_parse_list_callbacks << block
236
- end
237
-
238
- # Registers a callback to be called after a list of files is parsed
239
- # via {parse}. The block passed to this method will be called on
240
- # subsequent parse calls.
241
- #
242
- # @example Printing results after parsing occurs
243
- # SourceParser.after_parse_list do
244
- # puts "Finished parsing!"
245
- # end
246
- # YARD.parse
247
- # # Prints "Finished parsing!" after parsing files
248
- # @yield [files, globals] the yielded block is called once before
249
- # parsing all files
250
- # @yieldparam [Array<String>] files the list of files that will be parsed.
251
- # @yieldparam [OpenStruct] globals a global structure to store arbitrary
252
- # state for post processing (see {Handlers::Processor#globals})
253
- # @yieldreturn [void] the return value for the block is ignored.
254
- # @return [Proc] the yielded block
255
- # @see before_parse_list
256
- # @see before_parse_file
257
- # @since 0.7.0
258
- def after_parse_list(&block)
259
- after_parse_list_callbacks << block
260
- end
261
-
262
- # Registers a callback to be called before an individual file is parsed.
263
- # The block passed to this method will be called on subsequent parse
264
- # calls.
265
- #
266
- # To register a callback that is called before the entire list of files
267
- # is processed, see {before_parse_list}.
268
- #
269
- # @example Installing a simple callback
270
- # SourceParser.before_parse_file do |parser|
271
- # puts "I'm parsing #{parser.file}"
272
- # end
273
- # YARD.parse('lib/**/*.rb')
274
- # # prints:
275
- # "I'm parsing lib/foo.rb"
276
- # "I'm parsing lib/foo_bar.rb"
277
- # "I'm parsing lib/last_file.rb"
278
- #
279
- # @example Cancel parsing of any test_*.rb files
280
- # SourceParser.before_parse_file do |parser|
281
- # return false if parser.file =~ /^test_.+\.rb$/
282
- # end
283
- #
284
- # @yield [parser] the yielded block is called once before each
285
- # file that is parsed. This might happen many times for a single
286
- # codebase.
287
- # @yieldparam [SourceParser] parser the parser object that will {#parse}
288
- # the file.
289
- # @yieldreturn [Boolean] if the block returns +false+, parsing for
290
- # the file is cancelled.
291
- # @return [Proc] the yielded block
292
- # @see after_parse_file
293
- # @see before_parse_list
294
- # @since 0.7.0
295
- def before_parse_file(&block)
296
- before_parse_file_callbacks << block
297
- end
298
-
299
- # Registers a callback to be called after an individual file is parsed.
300
- # The block passed to this method will be called on subsequent parse
301
- # calls.
302
- #
303
- # To register a callback that is called after the entire list of files
304
- # is processed, see {after_parse_list}.
305
- #
306
- # @example Printing the length of each file after it is parsed
307
- # SourceParser.after_parse_file do |parser|
308
- # puts "#{parser.file} is #{parser.contents.size} characters"
309
- # end
310
- # YARD.parse('lib/**/*.rb')
311
- # # prints:
312
- # "lib/foo.rb is 1240 characters"
313
- # "lib/foo_bar.rb is 248 characters"
314
- #
315
- # @yield [parser] the yielded block is called once after each file
316
- # that is parsed. This might happen many times for a single codebase.
317
- # @yieldparam [SourceParser] parser the parser object that parsed
318
- # the file.
319
- # @yieldreturn [void] the return value for the block is ignored.
320
- # @return [Proc] the yielded block
321
- # @see before_parse_file
322
- # @see after_parse_list
323
- # @since 0.7.0
324
- def after_parse_file(&block)
325
- after_parse_file_callbacks << block
326
- end
327
-
328
- # @return [Array<Proc>] the list of callbacks to be called before
329
- # parsing a list of files. Should only be used for testing.
330
- # @since 0.7.0
331
- def before_parse_list_callbacks
332
- @before_parse_list_callbacks ||= []
333
- end
334
-
335
- # @return [Array<Proc>] the list of callbacks to be called after
336
- # parsing a list of files. Should only be used for testing.
337
- # @since 0.7.0
338
- def after_parse_list_callbacks
339
- @after_parse_list_callbacks ||= []
340
- end
341
-
342
- # @return [Array<Proc>] the list of callbacks to be called before
343
- # parsing a file. Should only be used for testing.
344
- # @since 0.7.0
345
- def before_parse_file_callbacks
346
- @before_parse_file_callbacks ||= []
347
- end
348
-
349
- # @return [Array<Proc>] the list of callbacks to be called after
350
- # parsing a file. Should only be used for testing.
351
- # @since 0.7.0
352
- def after_parse_file_callbacks
353
- @after_parse_file_callbacks ||= []
354
- end
355
-
356
- # @endgroup
357
-
358
- private
359
-
360
- # Parses a list of files in a queue.
361
- #
362
- # @param [Array<String>] files a list of files to queue for parsing
363
- # @return [void]
364
- def parse_in_order(*files)
365
- global_state = OpenStruct.new
366
-
367
- return if before_parse_list_callbacks.any? do |cb|
368
- cb.call(files, global_state) == false
369
- end
370
-
371
- OrderedParser.new(global_state, files).parse
372
-
373
- after_parse_list_callbacks.each do |cb|
374
- cb.call(files, global_state)
375
- end
376
- end
377
- end
378
-
379
- register_parser_type :ruby, Ruby::RubyParser
380
- register_parser_type :ruby18, Ruby::Legacy::RubyParser
381
- register_parser_type :c, C::CParser, ['c', 'cc', 'cxx', 'cpp']
382
-
383
- self.parser_type = :ruby
384
-
385
- # @return [String] the filename being parsed by the parser.
386
- attr_accessor :file
387
-
388
- # @return [Symbol] the parser type associated with the parser instance.
389
- # This should be set by the {#initialize constructor}.
390
- attr_reader :parser_type
391
-
392
- # @return [OpenStruct] an open struct containing arbitrary global state
393
- # shared between files and handlers.
394
- # @since 0.7.0
395
- attr_reader :globals
396
-
397
- # @return [String] the contents of the file to be parsed
398
- # @since 0.7.0
399
- attr_reader :contents
400
-
401
- # @overload initialize(parser_type = SourceParser.parser_type, globals = nil)
402
- # Creates a new parser object for code parsing with a specific parser type.
403
- #
404
- # @param [Symbol] parser_type the parser type to use
405
- # @param [OpenStruct] globals global state to be re-used across separate source files
406
- def initialize(parser_type = SourceParser.parser_type, globals1 = nil, globals2 = nil)
407
- globals = [true, false].include?(globals1) ? globals2 : globals1
408
- @file = '(stdin)'
409
- @globals = globals || OpenStruct.new
410
- self.parser_type = parser_type
411
- end
412
-
413
- # The main parser method. This should not be called directly. Instead,
414
- # use the class methods {parse} and {parse_string}.
415
- #
416
- # @param [String, #read, Object] content the source file to parse
417
- # @return [Object, nil] the parser object used to parse the source
418
- def parse(content = __FILE__)
419
- case content
420
- when String
421
- @file = File.cleanpath(content)
422
- content = convert_encoding(String.new(File.read_binary(file)))
423
- checksum = Registry.checksum_for(content)
424
- return if Registry.checksums[file] == checksum
425
-
426
- if Registry.checksums.key?(file)
427
- log.info "File '#{file}' was modified, re-processing..."
428
- end
429
- Registry.checksums[@file] = checksum
430
- self.parser_type = parser_type_for_filename(file)
431
- else
432
- content = content.read if content.respond_to? :read
433
- end
434
-
435
- @contents = content
436
- @parser = parser_class.new(content, file)
437
-
438
- self.class.before_parse_file_callbacks.each do |cb|
439
- return @parser if cb.call(self) == false
440
- end
441
-
442
- @parser.parse
443
- post_process
444
-
445
- self.class.after_parse_file_callbacks.each do |cb|
446
- cb.call(self)
447
- end
448
-
449
- @parser
450
- rescue ArgumentError, NotImplementedError => e
451
- log.warn("Cannot parse `#{file}': #{e.message}")
452
- log.backtrace(e, :warn)
453
- rescue ParserSyntaxError => e
454
- log.warn(e.message.capitalize)
455
- log.backtrace(e, :warn)
456
- end
457
-
458
- # Tokenizes but does not parse the block of code using the current {#parser_type}
459
- #
460
- # @param [String] content the block of code to tokenize
461
- # @return [Array] a list of tokens
462
- def tokenize(content)
463
- @parser = parser_class.new(content, file)
464
- @parser.tokenize
465
- end
466
-
467
- private
468
-
469
- # Searches for encoding line and forces encoding
470
- # @since 0.5.3
471
- def convert_encoding(content)
472
- return content unless content.respond_to?(:force_encoding)
473
- if content =~ ENCODING_LINE
474
- content.force_encoding($1)
475
- else
476
- content.force_encoding('binary')
477
- ENCODING_BYTE_ORDER_MARKS.each do |encoding, bom|
478
- bom.force_encoding('binary')
479
- if content[0, bom.size] == bom
480
- content.force_encoding(encoding)
481
- return content
482
- end
483
- end
484
- content.force_encoding('utf-8') # UTF-8 is default encoding
485
- content
486
- end
487
- end
488
-
489
- # Runs a {Handlers::Processor} object to post process the parsed statements.
490
- # @return [void]
491
- def post_process
492
- return unless @parser.respond_to?(:enumerator)
493
-
494
- enumerator = @parser.enumerator
495
- if enumerator
496
- post = Handlers::Processor.new(self)
497
- post.process(enumerator)
498
- end
499
- end
500
-
501
- def parser_type=(value)
502
- @parser_type = self.class.validated_parser_type(value)
503
- end
504
-
505
- # Guesses the parser type to use depending on the file extension.
506
- #
507
- # @param [String] filename the filename to use to guess the parser type
508
- # @return [Symbol] a parser type that matches the filename
509
- def parser_type_for_filename(filename)
510
- ext = (File.extname(filename)[1..-1] || "").downcase
511
- type = self.class.parser_type_for_extension(ext)
512
- parser_type == :ruby18 && type == :ruby ? :ruby18 : type
513
- end
514
-
515
- # @since 0.5.6
516
- def parser_class
517
- klass = self.class.parser_types[parser_type]
518
- unless klass
519
- raise ArgumentError, "invalid parser type '#{parser_type}' or unrecognized file", caller[1..-1]
520
- end
521
-
522
- klass
523
- end
524
- end
525
- end
526
- end
1
+ # frozen_string_literal: true
2
+ require 'stringio'
3
+ require 'ostruct'
4
+
5
+ module YARD
6
+ module Parser
7
+ # Raised when an object is recognized but cannot be documented. This
8
+ # generally occurs when the Ruby syntax used to declare an object is
9
+ # too dynamic in nature.
10
+ class UndocumentableError < RuntimeError; end
11
+
12
+ # Raised when the parser sees a Ruby syntax error
13
+ class ParserSyntaxError < UndocumentableError; end
14
+
15
+ # Responsible for parsing a list of files in order. The
16
+ # {#parse} method of this class can be called from the
17
+ # {SourceParser#globals} globals state list to re-enter
18
+ # parsing for the remainder of files in the list recursively.
19
+ #
20
+ # @see Processor#parse_remaining_files
21
+ class OrderedParser
22
+ # @return [Array<String>] the list of remaining files to parse
23
+ attr_accessor :files
24
+
25
+ # Creates a new OrderedParser with the global state and a list
26
+ # of files to parse.
27
+ #
28
+ # @note OrderedParser sets itself as the +ordered_parser+ key on
29
+ # global_state for later use in {Handlers::Processor}.
30
+ # @param [OpenStruct] global_state a structure containing all global
31
+ # state during parsing
32
+ # @param [Array<String>] files the list of files to parse
33
+ def initialize(global_state, files)
34
+ @global_state = global_state
35
+ @files = files.dup
36
+ @global_state.ordered_parser = self
37
+ end
38
+
39
+ # Parses the remainder of the {#files} list.
40
+ #
41
+ # @see Processor#parse_remaining_files
42
+ def parse
43
+ until files.empty?
44
+ file = files.shift
45
+ log.capture("Parsing #{file}") do
46
+ SourceParser.new(SourceParser.parser_type, @global_state).parse(file)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # Responsible for parsing a source file into the namespace. Parsing
53
+ # also invokes handlers to process the parsed statements and generate
54
+ # any code objects that may be recognized.
55
+ #
56
+ # == Custom Parsers
57
+ # SourceParser allows custom parsers to be registered and called when
58
+ # a certain filetype is recognized. To register a parser and hook it
59
+ # up to a set of file extensions, call {register_parser_type}
60
+ #
61
+ # @see register_parser_type
62
+ # @see Handlers::Base
63
+ # @see CodeObjects::Base
64
+ class SourceParser
65
+ SHEBANG_LINE = /\A\s*#!\S+/
66
+ ENCODING_LINE = %r{\A(?:\s*#*!.*\r?\n)?\s*(?:#+|/\*+|//+).*coding\s*[:=]{1,2}\s*([a-z\d_\-]+)}i
67
+ FROZEN_STRING_LINE = /frozen(-|_)string(-|_)literal: true/i
68
+
69
+ # The default glob of files to be parsed.
70
+ # @since 0.9.0
71
+ DEFAULT_PATH_GLOB = ["{lib,app}/**/*.rb", "ext/**/*.{c,cc,cxx,cpp,rb}"]
72
+
73
+ # Byte order marks for various encodings
74
+ # @since 0.7.0
75
+ ENCODING_BYTE_ORDER_MARKS = {
76
+ 'utf-8' => String.new("\xEF\xBB\xBF"),
77
+ # Not yet supported
78
+ # 'utf-16be' => "\xFE\xFF",
79
+ # 'utf-16le' => "\xFF\xFE",
80
+ # 'utf-32be' => "\x00\x00\xFF\xFE",
81
+ # 'utf-32le' => "\xFF\xFE",
82
+ }
83
+
84
+ class << self
85
+ # @return [Symbol] the default parser type (defaults to :ruby)
86
+ attr_reader :parser_type
87
+
88
+ def parser_type=(value)
89
+ @parser_type = validated_parser_type(value)
90
+ end
91
+
92
+ # Parses a path or set of paths
93
+ #
94
+ # @param [String, Array<String>] paths a path, glob, or list of paths to
95
+ # parse
96
+ # @param [Array<String, Regexp>] excluded a list of excluded path matchers
97
+ # @param [Fixnum] level the logger level to use during parsing. See
98
+ # {YARD::Logger}
99
+ # @return [void]
100
+ def parse(paths = DEFAULT_PATH_GLOB, excluded = [], level = log.level)
101
+ log.debug("Parsing #{paths.inspect} with `#{parser_type}` parser")
102
+ excluded = excluded.map do |path|
103
+ case path
104
+ when Regexp; path
105
+ else Regexp.new(path.to_s, Regexp::IGNORECASE)
106
+ end
107
+ end
108
+ files = [paths].flatten.
109
+ map {|p| File.directory?(p) ? "#{p}/**/*.{rb,c,cc,cxx,cpp}" : p }.
110
+ map {|p| p.include?("*") ? Dir[p].sort_by {|d| [d.length, d] } : p }.flatten.
111
+ reject {|p| !File.file?(p) || excluded.any? {|re| p =~ re } }
112
+
113
+ log.enter_level(level) do
114
+ parse_in_order(*files.uniq)
115
+ end
116
+ end
117
+
118
+ # Parses a string +content+
119
+ #
120
+ # @param [String] content the block of code to parse
121
+ # @param [Symbol] ptype the parser type to use. See {parser_type}.
122
+ # @return the parser object that was used to parse +content+
123
+ def parse_string(content, ptype = parser_type)
124
+ new(ptype).parse(StringIO.new(content))
125
+ end
126
+
127
+ # Tokenizes but does not parse the block of code
128
+ #
129
+ # @param [String] content the block of code to tokenize
130
+ # @param [Symbol] ptype the parser type to use. See {parser_type}.
131
+ # @return [Array] a list of tokens
132
+ def tokenize(content, ptype = parser_type)
133
+ new(ptype).tokenize(content)
134
+ end
135
+
136
+ # Registers a new parser type.
137
+ #
138
+ # @example Registering a parser for "java" files
139
+ # SourceParser.register_parser_type :java, JavaParser, 'java'
140
+ # @param [Symbol] type a symbolic name for the parser type
141
+ # @param [Base] parser_klass a class that implements parsing and tokenization
142
+ # @param [Array<String>, String, Regexp] extensions a list of extensions or a
143
+ # regex to match against the file extension
144
+ # @return [void]
145
+ # @see Parser::Base
146
+ def register_parser_type(type, parser_klass, extensions = nil)
147
+ unless Base > parser_klass
148
+ raise ArgumentError, "expecting parser_klass to be a subclass of YARD::Parser::Base"
149
+ end
150
+ parser_type_extensions[type.to_sym] = extensions if extensions
151
+ parser_types[type.to_sym] = parser_klass
152
+ end
153
+
154
+ # @return [Hash{Symbol=>Object}] a list of registered parser types
155
+ # @private
156
+ # @since 0.5.6
157
+ def parser_types; @@parser_types ||= {} end
158
+ def parser_types=(value) @@parser_types = value end
159
+
160
+ # @return [Hash] a list of registered parser type extensions
161
+ # @private
162
+ # @since 0.5.6
163
+ def parser_type_extensions; @@parser_type_extensions ||= {} end
164
+ def parser_type_extensions=(value) @@parser_type_extensions = value end
165
+
166
+ # Finds a parser type that is registered for the extension. If no
167
+ # type is found, the default Ruby type is returned.
168
+ #
169
+ # @return [Symbol] the parser type to be used for the extension
170
+ # @since 0.5.6
171
+ def parser_type_for_extension(extension)
172
+ type = parser_type_extensions.find do |_t, exts|
173
+ [exts].flatten.any? {|ext| ext === extension }
174
+ end
175
+ validated_parser_type(type ? type.first : :ruby)
176
+ end
177
+
178
+ # Returns the validated parser type. Basically, enforces that :ruby
179
+ # type is never set if the Ripper library is not available
180
+ #
181
+ # @param [Symbol] type the parser type to set
182
+ # @return [Symbol] the validated parser type
183
+ # @private
184
+ def validated_parser_type(type)
185
+ !defined?(::Ripper) && type == :ruby ? :ruby18 : type
186
+ end
187
+
188
+ # @group Parser Callbacks
189
+
190
+ # Registers a callback to be called before a list of files is parsed
191
+ # via {parse}. The block passed to this method will be called on
192
+ # subsequent parse calls.
193
+ #
194
+ # @example Installing a simple callback
195
+ # SourceParser.before_parse_list do |files, globals|
196
+ # puts "Starting to parse..."
197
+ # end
198
+ # YARD.parse('lib/**/*.rb')
199
+ # # prints "Starting to parse..."
200
+ #
201
+ # @example Setting global state
202
+ # SourceParser.before_parse_list do |files, globals|
203
+ # globals.method_count = 0
204
+ # end
205
+ # SourceParser.after_parse_list do |files, globals|
206
+ # puts "Found #{globals.method_count} methods"
207
+ # end
208
+ # class MyCountHandler < Handlers::Ruby::Base
209
+ # handles :def, :defs
210
+ # process { globals.method_count += 1 }
211
+ # end
212
+ # YARD.parse
213
+ # # Prints: "Found 37 methods"
214
+ #
215
+ # @example Using a global callback to cancel parsing
216
+ # SourceParser.before_parse_list do |files, globals|
217
+ # return false if files.include?('foo.rb')
218
+ # end
219
+ #
220
+ # YARD.parse(['foo.rb', 'bar.rb']) # callback cancels this method
221
+ # YARD.parse('bar.rb') # parses normally
222
+ #
223
+ # @yield [files, globals] the yielded block is called once before
224
+ # parsing all files
225
+ # @yieldparam [Array<String>] files the list of files that will be parsed.
226
+ # @yieldparam [OpenStruct] globals a global structure to store arbitrary
227
+ # state for post processing (see {Handlers::Processor#globals})
228
+ # @yieldreturn [Boolean] if the block returns +false+, parsing is
229
+ # cancelled.
230
+ # @return [Proc] the yielded block
231
+ # @see after_parse_list
232
+ # @see before_parse_file
233
+ # @since 0.7.0
234
+ def before_parse_list(&block)
235
+ before_parse_list_callbacks << block
236
+ end
237
+
238
+ # Registers a callback to be called after a list of files is parsed
239
+ # via {parse}. The block passed to this method will be called on
240
+ # subsequent parse calls.
241
+ #
242
+ # @example Printing results after parsing occurs
243
+ # SourceParser.after_parse_list do
244
+ # puts "Finished parsing!"
245
+ # end
246
+ # YARD.parse
247
+ # # Prints "Finished parsing!" after parsing files
248
+ # @yield [files, globals] the yielded block is called once before
249
+ # parsing all files
250
+ # @yieldparam [Array<String>] files the list of files that will be parsed.
251
+ # @yieldparam [OpenStruct] globals a global structure to store arbitrary
252
+ # state for post processing (see {Handlers::Processor#globals})
253
+ # @yieldreturn [void] the return value for the block is ignored.
254
+ # @return [Proc] the yielded block
255
+ # @see before_parse_list
256
+ # @see before_parse_file
257
+ # @since 0.7.0
258
+ def after_parse_list(&block)
259
+ after_parse_list_callbacks << block
260
+ end
261
+
262
+ # Registers a callback to be called before an individual file is parsed.
263
+ # The block passed to this method will be called on subsequent parse
264
+ # calls.
265
+ #
266
+ # To register a callback that is called before the entire list of files
267
+ # is processed, see {before_parse_list}.
268
+ #
269
+ # @example Installing a simple callback
270
+ # SourceParser.before_parse_file do |parser|
271
+ # puts "I'm parsing #{parser.file}"
272
+ # end
273
+ # YARD.parse('lib/**/*.rb')
274
+ # # prints:
275
+ # "I'm parsing lib/foo.rb"
276
+ # "I'm parsing lib/foo_bar.rb"
277
+ # "I'm parsing lib/last_file.rb"
278
+ #
279
+ # @example Cancel parsing of any test_*.rb files
280
+ # SourceParser.before_parse_file do |parser|
281
+ # return false if parser.file =~ /^test_.+\.rb$/
282
+ # end
283
+ #
284
+ # @yield [parser] the yielded block is called once before each
285
+ # file that is parsed. This might happen many times for a single
286
+ # codebase.
287
+ # @yieldparam [SourceParser] parser the parser object that will {#parse}
288
+ # the file.
289
+ # @yieldreturn [Boolean] if the block returns +false+, parsing for
290
+ # the file is cancelled.
291
+ # @return [Proc] the yielded block
292
+ # @see after_parse_file
293
+ # @see before_parse_list
294
+ # @since 0.7.0
295
+ def before_parse_file(&block)
296
+ before_parse_file_callbacks << block
297
+ end
298
+
299
+ # Registers a callback to be called after an individual file is parsed.
300
+ # The block passed to this method will be called on subsequent parse
301
+ # calls.
302
+ #
303
+ # To register a callback that is called after the entire list of files
304
+ # is processed, see {after_parse_list}.
305
+ #
306
+ # @example Printing the length of each file after it is parsed
307
+ # SourceParser.after_parse_file do |parser|
308
+ # puts "#{parser.file} is #{parser.contents.size} characters"
309
+ # end
310
+ # YARD.parse('lib/**/*.rb')
311
+ # # prints:
312
+ # "lib/foo.rb is 1240 characters"
313
+ # "lib/foo_bar.rb is 248 characters"
314
+ #
315
+ # @yield [parser] the yielded block is called once after each file
316
+ # that is parsed. This might happen many times for a single codebase.
317
+ # @yieldparam [SourceParser] parser the parser object that parsed
318
+ # the file.
319
+ # @yieldreturn [void] the return value for the block is ignored.
320
+ # @return [Proc] the yielded block
321
+ # @see before_parse_file
322
+ # @see after_parse_list
323
+ # @since 0.7.0
324
+ def after_parse_file(&block)
325
+ after_parse_file_callbacks << block
326
+ end
327
+
328
+ # @return [Array<Proc>] the list of callbacks to be called before
329
+ # parsing a list of files. Should only be used for testing.
330
+ # @since 0.7.0
331
+ def before_parse_list_callbacks
332
+ @before_parse_list_callbacks ||= []
333
+ end
334
+
335
+ # @return [Array<Proc>] the list of callbacks to be called after
336
+ # parsing a list of files. Should only be used for testing.
337
+ # @since 0.7.0
338
+ def after_parse_list_callbacks
339
+ @after_parse_list_callbacks ||= []
340
+ end
341
+
342
+ # @return [Array<Proc>] the list of callbacks to be called before
343
+ # parsing a file. Should only be used for testing.
344
+ # @since 0.7.0
345
+ def before_parse_file_callbacks
346
+ @before_parse_file_callbacks ||= []
347
+ end
348
+
349
+ # @return [Array<Proc>] the list of callbacks to be called after
350
+ # parsing a file. Should only be used for testing.
351
+ # @since 0.7.0
352
+ def after_parse_file_callbacks
353
+ @after_parse_file_callbacks ||= []
354
+ end
355
+
356
+ # @endgroup
357
+
358
+ private
359
+
360
+ # Parses a list of files in a queue.
361
+ #
362
+ # @param [Array<String>] files a list of files to queue for parsing
363
+ # @return [void]
364
+ def parse_in_order(*files)
365
+ global_state = OpenStruct.new
366
+
367
+ return if before_parse_list_callbacks.any? do |cb|
368
+ cb.call(files, global_state) == false
369
+ end
370
+
371
+ OrderedParser.new(global_state, files).parse
372
+
373
+ after_parse_list_callbacks.each do |cb|
374
+ cb.call(files, global_state)
375
+ end
376
+ end
377
+ end
378
+
379
+ register_parser_type :ruby, Ruby::RubyParser
380
+ register_parser_type :ruby18, Ruby::Legacy::RubyParser
381
+ register_parser_type :c, C::CParser, ['c', 'cc', 'cxx', 'cpp']
382
+
383
+ self.parser_type = :ruby
384
+
385
+ # @return [String] the filename being parsed by the parser.
386
+ attr_accessor :file
387
+
388
+ # @return [Symbol] the parser type associated with the parser instance.
389
+ # This should be set by the {#initialize constructor}.
390
+ attr_reader :parser_type
391
+
392
+ # @return [OpenStruct] an open struct containing arbitrary global state
393
+ # shared between files and handlers.
394
+ # @since 0.7.0
395
+ attr_reader :globals
396
+
397
+ # @return [String] the contents of the file to be parsed
398
+ # @since 0.7.0
399
+ attr_reader :contents
400
+
401
+ # @overload initialize(parser_type = SourceParser.parser_type, globals = nil)
402
+ # Creates a new parser object for code parsing with a specific parser type.
403
+ #
404
+ # @param [Symbol] parser_type the parser type to use
405
+ # @param [OpenStruct] globals global state to be re-used across separate source files
406
+ def initialize(parser_type = SourceParser.parser_type, globals1 = nil, globals2 = nil)
407
+ globals = [true, false].include?(globals1) ? globals2 : globals1
408
+ @file = '(stdin)'
409
+ @globals = globals || OpenStruct.new
410
+ self.parser_type = parser_type
411
+ end
412
+
413
+ # The main parser method. This should not be called directly. Instead,
414
+ # use the class methods {parse} and {parse_string}.
415
+ #
416
+ # @param [String, #read, Object] content the source file to parse
417
+ # @return [Object, nil] the parser object used to parse the source
418
+ def parse(content = __FILE__)
419
+ case content
420
+ when String
421
+ @file = File.cleanpath(content)
422
+ content = convert_encoding(String.new(File.read_binary(file)))
423
+ checksum = Registry.checksum_for(content)
424
+ return if Registry.checksums[file] == checksum
425
+
426
+ if Registry.checksums.key?(file)
427
+ log.info "File '#{file}' was modified, re-processing..."
428
+ end
429
+ Registry.checksums[@file] = checksum
430
+ self.parser_type = parser_type_for_filename(file)
431
+ else
432
+ content = content.read if content.respond_to? :read
433
+ end
434
+
435
+ @contents = content
436
+ @parser = parser_class.new(content, file)
437
+
438
+ self.class.before_parse_file_callbacks.each do |cb|
439
+ return @parser if cb.call(self) == false
440
+ end
441
+
442
+ @parser.parse
443
+ post_process
444
+
445
+ self.class.after_parse_file_callbacks.each do |cb|
446
+ cb.call(self)
447
+ end
448
+
449
+ @parser
450
+ rescue ArgumentError, NotImplementedError => e
451
+ log.warn("Cannot parse `#{file}': #{e.message}")
452
+ log.backtrace(e, :warn)
453
+ rescue ParserSyntaxError => e
454
+ log.warn(e.message.capitalize)
455
+ log.backtrace(e, :warn)
456
+ end
457
+
458
+ # Tokenizes but does not parse the block of code using the current {#parser_type}
459
+ #
460
+ # @param [String] content the block of code to tokenize
461
+ # @return [Array] a list of tokens
462
+ def tokenize(content)
463
+ @parser = parser_class.new(content, file)
464
+ @parser.tokenize
465
+ end
466
+
467
+ private
468
+
469
+ # Searches for encoding line and forces encoding
470
+ # @since 0.5.3
471
+ def convert_encoding(content)
472
+ return content unless content.respond_to?(:force_encoding)
473
+ if content =~ ENCODING_LINE
474
+ content.force_encoding($1)
475
+ else
476
+ content.force_encoding('binary')
477
+ ENCODING_BYTE_ORDER_MARKS.each do |encoding, bom|
478
+ bom.force_encoding('binary')
479
+ if content[0, bom.size] == bom
480
+ content.force_encoding(encoding)
481
+ return content
482
+ end
483
+ end
484
+ content.force_encoding('utf-8') # UTF-8 is default encoding
485
+ content
486
+ end
487
+ end
488
+
489
+ # Runs a {Handlers::Processor} object to post process the parsed statements.
490
+ # @return [void]
491
+ def post_process
492
+ return unless @parser.respond_to?(:enumerator)
493
+
494
+ enumerator = @parser.enumerator
495
+ if enumerator
496
+ post = Handlers::Processor.new(self)
497
+ post.process(enumerator)
498
+ end
499
+ end
500
+
501
+ def parser_type=(value)
502
+ @parser_type = self.class.validated_parser_type(value)
503
+ end
504
+
505
+ # Guesses the parser type to use depending on the file extension.
506
+ #
507
+ # @param [String] filename the filename to use to guess the parser type
508
+ # @return [Symbol] a parser type that matches the filename
509
+ def parser_type_for_filename(filename)
510
+ ext = (File.extname(filename)[1..-1] || "").downcase
511
+ type = self.class.parser_type_for_extension(ext)
512
+ parser_type == :ruby18 && type == :ruby ? :ruby18 : type
513
+ end
514
+
515
+ # @since 0.5.6
516
+ def parser_class
517
+ klass = self.class.parser_types[parser_type]
518
+ unless klass
519
+ raise ArgumentError, "invalid parser type '#{parser_type}' or unrecognized file", caller[1..-1]
520
+ end
521
+
522
+ klass
523
+ end
524
+ end
525
+ end
526
+ end