yard 0.7.5 → 0.8.0

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 (339) hide show
  1. data/.yardopts +10 -2
  2. data/ChangeLog +1263 -38
  3. data/LEGAL +5 -5
  4. data/LICENSE +1 -1
  5. data/README.md +91 -82
  6. data/Rakefile +6 -6
  7. data/benchmarks/builtins_vs_eval.rb +1 -1
  8. data/benchmarks/erb_vs_erubis.rb +4 -4
  9. data/benchmarks/generation.rb +5 -5
  10. data/benchmarks/parsing.rb +2 -2
  11. data/benchmarks/registry_store_types.rb +48 -0
  12. data/bin/yard +9 -1
  13. data/bin/yardoc +9 -1
  14. data/bin/yri +10 -2
  15. data/docs/CodeObjects.md +10 -10
  16. data/docs/GettingStarted.md +85 -83
  17. data/docs/Handlers.md +21 -21
  18. data/docs/Overview.md +7 -7
  19. data/docs/Parser.md +30 -30
  20. data/docs/Tags.md +250 -554
  21. data/docs/TagsArch.md +123 -0
  22. data/docs/Templates.md +58 -80
  23. data/docs/WhatsNew.md +378 -133
  24. data/docs/templates/default/fulldoc/html/full_list_tag.erb +7 -0
  25. data/docs/templates/default/fulldoc/html/setup.rb +6 -0
  26. data/docs/templates/default/layout/html/setup.rb +8 -0
  27. data/docs/templates/default/layout/html/tag_list.erb +11 -0
  28. data/docs/templates/default/yard_tags/html/list.erb +18 -0
  29. data/docs/templates/default/yard_tags/html/setup.rb +27 -0
  30. data/docs/templates/plugin.rb +65 -0
  31. data/lib/yard.rb +1 -10
  32. data/lib/yard/autoload.rb +75 -27
  33. data/lib/yard/cli/command.rb +5 -2
  34. data/lib/yard/cli/command_parser.rb +3 -2
  35. data/lib/yard/cli/diff.rb +1 -1
  36. data/lib/yard/cli/i18n.rb +69 -0
  37. data/lib/yard/cli/list.rb +1 -1
  38. data/lib/yard/cli/server.rb +30 -7
  39. data/lib/yard/cli/stats.rb +5 -6
  40. data/lib/yard/cli/yardoc.rb +95 -45
  41. data/lib/yard/cli/yri.rb +24 -3
  42. data/lib/yard/code_objects/base.rb +35 -4
  43. data/lib/yard/code_objects/extra_file_object.rb +1 -1
  44. data/lib/yard/code_objects/macro_object.rb +56 -99
  45. data/lib/yard/code_objects/method_object.rb +44 -6
  46. data/lib/yard/config.rb +18 -8
  47. data/lib/yard/core_ext/symbol_hash.rb +1 -1
  48. data/lib/yard/docstring.rb +45 -85
  49. data/lib/yard/docstring_parser.rb +269 -0
  50. data/lib/yard/handlers/base.rb +129 -118
  51. data/lib/yard/handlers/c/alias_handler.rb +15 -0
  52. data/lib/yard/handlers/c/attribute_handler.rb +13 -0
  53. data/lib/yard/handlers/c/base.rb +110 -0
  54. data/lib/yard/handlers/c/class_handler.rb +26 -0
  55. data/lib/yard/handlers/c/constant_handler.rb +12 -0
  56. data/lib/yard/handlers/c/handler_methods.rb +165 -0
  57. data/lib/yard/handlers/c/init_handler.rb +16 -0
  58. data/lib/yard/handlers/c/method_handler.rb +35 -0
  59. data/lib/yard/handlers/c/mixin_handler.rb +13 -0
  60. data/lib/yard/handlers/c/module_handler.rb +16 -0
  61. data/lib/yard/handlers/c/override_comment_handler.rb +22 -0
  62. data/lib/yard/handlers/c/path_handler.rb +10 -0
  63. data/lib/yard/handlers/c/struct_handler.rb +12 -0
  64. data/lib/yard/handlers/c/symbol_handler.rb +7 -0
  65. data/lib/yard/handlers/processor.rb +41 -30
  66. data/lib/yard/handlers/ruby/alias_handler.rb +0 -2
  67. data/lib/yard/handlers/ruby/attribute_handler.rb +16 -17
  68. data/lib/yard/handlers/ruby/base.rb +10 -6
  69. data/lib/yard/handlers/ruby/comment_handler.rb +9 -0
  70. data/lib/yard/handlers/ruby/dsl_handler.rb +14 -0
  71. data/lib/yard/handlers/ruby/dsl_handler_methods.rb +71 -0
  72. data/lib/yard/handlers/ruby/legacy/alias_handler.rb +0 -3
  73. data/lib/yard/handlers/ruby/legacy/attribute_handler.rb +16 -17
  74. data/lib/yard/handlers/ruby/legacy/base.rb +28 -6
  75. data/lib/yard/handlers/ruby/legacy/comment_handler.rb +9 -0
  76. data/lib/yard/handlers/ruby/legacy/dsl_handler.rb +16 -0
  77. data/lib/yard/handlers/ruby/legacy/method_handler.rb +0 -2
  78. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +1 -1
  79. data/lib/yard/handlers/ruby/legacy/module_function_handler.rb +18 -0
  80. data/lib/yard/handlers/ruby/method_handler.rb +10 -15
  81. data/lib/yard/handlers/ruby/mixin_handler.rb +1 -1
  82. data/lib/yard/handlers/ruby/module_function_handler.rb +26 -0
  83. data/lib/yard/handlers/ruby/struct_handler_methods.rb +3 -2
  84. data/lib/yard/i18n/pot_generator.rb +281 -0
  85. data/lib/yard/i18n/text.rb +72 -0
  86. data/lib/yard/logging.rb +3 -7
  87. data/lib/yard/options.rb +216 -0
  88. data/lib/yard/parser/c/c_parser.rb +225 -0
  89. data/lib/yard/parser/c/comment_parser.rb +131 -0
  90. data/lib/yard/parser/c/statement.rb +63 -0
  91. data/lib/yard/parser/ruby/ast_node.rb +91 -1
  92. data/lib/yard/parser/ruby/legacy/ruby_parser.rb +1 -0
  93. data/lib/yard/parser/ruby/legacy/statement.rb +7 -2
  94. data/lib/yard/parser/ruby/legacy/statement_list.rb +13 -22
  95. data/lib/yard/parser/ruby/ruby_parser.rb +87 -26
  96. data/lib/yard/parser/source_parser.rb +89 -88
  97. data/lib/yard/rake/yardoc_task.rb +1 -1
  98. data/lib/yard/registry.rb +21 -10
  99. data/lib/yard/registry_store.rb +48 -0
  100. data/lib/yard/serializers/file_system_serializer.rb +18 -20
  101. data/lib/yard/serializers/yardoc_serializer.rb +1 -0
  102. data/lib/yard/server/adapter.rb +2 -2
  103. data/lib/yard/server/commands/base.rb +1 -1
  104. data/lib/yard/server/commands/display_object_command.rb +13 -6
  105. data/lib/yard/server/commands/frames_command.rb +4 -21
  106. data/lib/yard/server/commands/library_command.rb +57 -11
  107. data/lib/yard/server/commands/list_command.rb +10 -34
  108. data/lib/yard/server/commands/search_command.rb +8 -2
  109. data/lib/yard/server/doc_server_helper.rb +34 -0
  110. data/lib/yard/server/rack_adapter.rb +5 -1
  111. data/lib/yard/server/router.rb +4 -10
  112. data/lib/yard/server/static_caching.rb +2 -2
  113. data/lib/yard/server/templates/default/fulldoc/html/css/custom.css +2 -2
  114. data/lib/yard/server/templates/default/fulldoc/html/js/live.js +0 -15
  115. data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +3 -3
  116. data/lib/yard/server/templates/default/layout/html/script_setup.erb +8 -0
  117. data/lib/yard/server/templates/doc_server/processing/html/processing.erb +1 -1
  118. data/lib/yard/server/templates/doc_server/search/html/setup.rb +1 -1
  119. data/lib/yard/tags/default_factory.rb +31 -4
  120. data/lib/yard/tags/directives.rb +593 -0
  121. data/lib/yard/tags/library.rb +437 -35
  122. data/lib/yard/templates/engine.rb +17 -12
  123. data/lib/yard/templates/helpers/base_helper.rb +8 -2
  124. data/lib/yard/templates/helpers/html_helper.rb +57 -14
  125. data/lib/yard/templates/helpers/markup/rdoc_markup.rb +1 -1
  126. data/lib/yard/templates/helpers/markup_helper.rb +9 -9
  127. data/lib/yard/templates/helpers/text_helper.rb +2 -2
  128. data/lib/yard/templates/template.rb +42 -13
  129. data/lib/yard/templates/template_options.rb +81 -0
  130. data/spec/cli/command_parser_spec.rb +4 -4
  131. data/spec/cli/command_spec.rb +3 -3
  132. data/spec/cli/config_spec.rb +13 -13
  133. data/spec/cli/diff_spec.rb +13 -10
  134. data/spec/cli/gems_spec.rb +12 -12
  135. data/spec/cli/help_spec.rb +2 -2
  136. data/spec/cli/i18n_spec.rb +111 -0
  137. data/spec/cli/server_spec.rb +66 -18
  138. data/spec/cli/stats_spec.rb +15 -15
  139. data/spec/cli/yardoc_spec.rb +124 -97
  140. data/spec/cli/yri_spec.rb +14 -12
  141. data/spec/code_objects/base_spec.rb +104 -46
  142. data/spec/code_objects/class_object_spec.rb +33 -33
  143. data/spec/code_objects/code_object_list_spec.rb +5 -5
  144. data/spec/code_objects/constants_spec.rb +4 -3
  145. data/spec/code_objects/extra_file_object_spec.rb +19 -19
  146. data/spec/code_objects/macro_object_spec.rb +31 -37
  147. data/spec/code_objects/method_object_spec.rb +46 -23
  148. data/spec/code_objects/module_object_spec.rb +16 -16
  149. data/spec/code_objects/namespace_object_spec.rb +6 -6
  150. data/spec/code_objects/proxy_spec.rb +19 -19
  151. data/spec/config_spec.rb +33 -24
  152. data/spec/core_ext/array_spec.rb +1 -1
  153. data/spec/core_ext/file_spec.rb +8 -8
  154. data/spec/core_ext/hash_spec.rb +1 -1
  155. data/spec/core_ext/insertion_spec.rb +3 -3
  156. data/spec/core_ext/module_spec.rb +1 -1
  157. data/spec/core_ext/string_spec.rb +6 -6
  158. data/spec/core_ext/symbol_hash_spec.rb +11 -11
  159. data/spec/docstring_parser_spec.rb +207 -0
  160. data/spec/docstring_spec.rb +33 -146
  161. data/spec/handlers/alias_handler_spec.rb +14 -14
  162. data/spec/handlers/attribute_handler_spec.rb +20 -20
  163. data/spec/handlers/base_spec.rb +16 -16
  164. data/spec/handlers/c/alias_handler_spec.rb +33 -0
  165. data/spec/handlers/c/attribute_handler_spec.rb +40 -0
  166. data/spec/handlers/c/class_handler_spec.rb +64 -0
  167. data/spec/handlers/c/constant_handler_spec.rb +68 -0
  168. data/spec/handlers/c/init_handler_spec.rb +36 -0
  169. data/spec/handlers/c/method_handler_spec.rb +228 -0
  170. data/spec/handlers/c/mixin_handler_spec.rb +27 -0
  171. data/spec/handlers/c/module_handler_spec.rb +38 -0
  172. data/spec/handlers/c/override_comment_handler_spec.rb +43 -0
  173. data/spec/handlers/c/path_handler_spec.rb +35 -0
  174. data/spec/handlers/c/spec_helper.rb +11 -0
  175. data/spec/handlers/c/struct_handler_spec.rb +15 -0
  176. data/spec/handlers/class_condition_handler_spec.rb +10 -10
  177. data/spec/handlers/class_handler_spec.rb +38 -38
  178. data/spec/handlers/class_variable_handler_spec.rb +1 -1
  179. data/spec/handlers/constant_handler_spec.rb +7 -7
  180. data/spec/handlers/{macro_handler_spec.rb → dsl_handler_spec.rb} +72 -53
  181. data/spec/handlers/examples/alias_handler_001.rb.txt +5 -5
  182. data/spec/handlers/examples/class_condition_handler_001.rb.txt +9 -9
  183. data/spec/handlers/examples/class_handler_001.rb.txt +1 -1
  184. data/spec/handlers/examples/dsl_handler_001.rb.txt +110 -0
  185. data/spec/handlers/examples/exception_handler_001.rb.txt +14 -14
  186. data/spec/handlers/examples/method_condition_handler_001.rb.txt +2 -2
  187. data/spec/handlers/examples/method_handler_001.rb.txt +16 -16
  188. data/spec/handlers/examples/mixin_handler_001.rb.txt +8 -4
  189. data/spec/handlers/examples/private_constant_handler_001.rb.txt +1 -1
  190. data/spec/handlers/examples/visibility_handler_001.rb.txt +3 -3
  191. data/spec/handlers/examples/yield_handler_001.rb.txt +13 -14
  192. data/spec/handlers/exception_handler_spec.rb +9 -9
  193. data/spec/handlers/extend_handler_spec.rb +2 -2
  194. data/spec/handlers/legacy_base_spec.rb +34 -34
  195. data/spec/handlers/method_condition_handler_spec.rb +2 -2
  196. data/spec/handlers/method_handler_spec.rb +33 -33
  197. data/spec/handlers/mixin_handler_spec.rb +13 -9
  198. data/spec/handlers/module_function_handler_spec.rb +82 -0
  199. data/spec/handlers/module_handler_spec.rb +6 -6
  200. data/spec/handlers/private_constant_handler_spec.rb +3 -3
  201. data/spec/handlers/processor_spec.rb +5 -5
  202. data/spec/handlers/ruby/base_spec.rb +10 -6
  203. data/spec/handlers/ruby/legacy/base_spec.rb +11 -7
  204. data/spec/handlers/spec_helper.rb +2 -3
  205. data/spec/handlers/visibility_handler_spec.rb +6 -6
  206. data/spec/handlers/yield_handler_spec.rb +8 -8
  207. data/spec/i18n/pot_generator_spec.rb +244 -0
  208. data/spec/i18n/text_spec.rb +69 -0
  209. data/spec/options_spec.rb +160 -0
  210. data/spec/parser/base_spec.rb +3 -3
  211. data/spec/parser/c_parser_spec.rb +31 -257
  212. data/spec/parser/examples/array.c.txt +187 -187
  213. data/spec/parser/examples/extrafile.c.txt +1 -1
  214. data/spec/parser/examples/override.c.txt +1 -1
  215. data/spec/parser/ruby/ast_node_spec.rb +1 -1
  216. data/spec/parser/ruby/legacy/statement_list_spec.rb +24 -24
  217. data/spec/parser/ruby/legacy/token_list_spec.rb +7 -7
  218. data/spec/parser/ruby/ruby_parser_spec.rb +56 -34
  219. data/spec/parser/source_parser_spec.rb +125 -65
  220. data/spec/parser/tag_parsing_spec.rb +4 -4
  221. data/spec/rake/yardoc_task_spec.rb +10 -8
  222. data/spec/registry_spec.rb +65 -36
  223. data/spec/registry_store_spec.rb +90 -40
  224. data/spec/serializers/file_system_serializer_spec.rb +12 -12
  225. data/spec/serializers/yardoc_serializer_spec.rb +2 -2
  226. data/spec/server/adapter_spec.rb +3 -3
  227. data/spec/server/commands/base_spec.rb +8 -8
  228. data/spec/server/commands/library_command_spec.rb +3 -3
  229. data/spec/server/commands/static_file_command_spec.rb +7 -7
  230. data/spec/server/doc_server_helper_spec.rb +1 -1
  231. data/spec/server/doc_server_serializer_spec.rb +6 -6
  232. data/spec/server/rack_adapter_spec.rb +3 -3
  233. data/spec/server/router_spec.rb +19 -19
  234. data/spec/server/static_caching_spec.rb +4 -4
  235. data/spec/spec_helper.rb +7 -7
  236. data/spec/tags/default_factory_spec.rb +24 -16
  237. data/spec/tags/directives_spec.rb +422 -0
  238. data/spec/tags/library_spec.rb +15 -4
  239. data/spec/tags/overload_tag_spec.rb +6 -6
  240. data/spec/tags/ref_tag_list_spec.rb +8 -8
  241. data/spec/templates/class_spec.rb +7 -7
  242. data/spec/templates/constant_spec.rb +7 -7
  243. data/spec/templates/engine_spec.rb +28 -36
  244. data/spec/templates/examples/class001.html +108 -108
  245. data/spec/templates/examples/class002.html +17 -17
  246. data/spec/templates/examples/constant001.txt +1 -1
  247. data/spec/templates/examples/method001.html +45 -45
  248. data/spec/templates/examples/method002.html +25 -25
  249. data/spec/templates/examples/method003.html +60 -60
  250. data/spec/templates/examples/method004.html +7 -7
  251. data/spec/templates/examples/method005.html +28 -28
  252. data/spec/templates/examples/module001.html +321 -321
  253. data/spec/templates/examples/module001.txt +1 -1
  254. data/spec/templates/examples/module002.html +130 -130
  255. data/spec/templates/examples/module003.html +74 -74
  256. data/spec/templates/examples/module004.html +388 -0
  257. data/spec/templates/helpers/base_helper_spec.rb +32 -32
  258. data/spec/templates/helpers/html_helper_spec.rb +87 -68
  259. data/spec/templates/helpers/html_syntax_highlight_helper_spec.rb +9 -9
  260. data/spec/templates/helpers/markup/rdoc_markup_spec.rb +16 -16
  261. data/spec/templates/helpers/markup_helper_spec.rb +31 -28
  262. data/spec/templates/helpers/method_helper_spec.rb +7 -7
  263. data/spec/templates/helpers/shared_signature_examples.rb +9 -7
  264. data/spec/templates/helpers/text_helper_spec.rb +3 -3
  265. data/spec/templates/method_spec.rb +13 -13
  266. data/spec/templates/module_spec.rb +70 -24
  267. data/spec/templates/onefile_spec.rb +32 -15
  268. data/spec/templates/section_spec.rb +23 -23
  269. data/spec/templates/spec_helper.rb +31 -1
  270. data/spec/templates/tag_spec.rb +5 -5
  271. data/spec/templates/template_spec.rb +54 -46
  272. data/spec/verifier_spec.rb +5 -5
  273. data/templates/default/class/setup.rb +2 -2
  274. data/templates/default/docstring/html/abstract.erb +1 -1
  275. data/templates/default/docstring/html/note.erb +1 -1
  276. data/templates/default/docstring/html/private.erb +1 -1
  277. data/templates/default/docstring/html/todo.erb +1 -1
  278. data/templates/default/docstring/setup.rb +2 -2
  279. data/templates/default/fulldoc/html/css/full_list.css +4 -2
  280. data/templates/default/fulldoc/html/css/style.css +50 -44
  281. data/templates/default/fulldoc/html/frames.erb +21 -6
  282. data/templates/default/fulldoc/html/full_list.erb +5 -3
  283. data/templates/default/fulldoc/html/{full_list_files.erb → full_list_file.erb} +0 -0
  284. data/templates/default/fulldoc/html/js/app.js +29 -26
  285. data/templates/default/fulldoc/html/js/full_list.js +9 -9
  286. data/templates/default/fulldoc/html/js/jquery.js +4 -16
  287. data/templates/default/fulldoc/html/setup.rb +42 -38
  288. data/templates/default/layout/dot/header.erb +1 -1
  289. data/templates/default/layout/html/breadcrumb.erb +6 -6
  290. data/templates/default/layout/html/files.erb +1 -1
  291. data/templates/default/layout/html/footer.erb +1 -1
  292. data/templates/default/layout/html/headers.erb +3 -6
  293. data/templates/default/layout/html/index.erb +1 -1
  294. data/templates/default/layout/html/layout.erb +3 -7
  295. data/templates/default/layout/html/objects.erb +1 -1
  296. data/templates/default/layout/html/script_setup.erb +5 -0
  297. data/templates/default/layout/html/search.erb +4 -1
  298. data/templates/default/layout/html/setup.rb +8 -8
  299. data/templates/default/method_details/html/method_signature.erb +10 -3
  300. data/templates/default/method_details/setup.rb +1 -0
  301. data/templates/default/module/dot/info.erb +1 -1
  302. data/templates/default/module/dot/setup.rb +2 -2
  303. data/templates/default/module/html/attribute_details.erb +1 -1
  304. data/templates/default/module/html/children.erb +1 -1
  305. data/templates/default/module/html/defines.erb +1 -1
  306. data/templates/default/module/html/inherited_methods.erb +5 -4
  307. data/templates/default/module/html/item_summary.erb +15 -5
  308. data/templates/default/module/html/method_details_list.erb +2 -2
  309. data/templates/default/module/setup.rb +25 -12
  310. data/templates/default/module/text/setup.rb +1 -1
  311. data/templates/default/onefile/html/layout.erb +1 -1
  312. data/templates/default/onefile/html/setup.rb +2 -2
  313. data/templates/default/tags/html/example.erb +4 -2
  314. data/templates/default/tags/html/option.erb +1 -1
  315. data/templates/default/tags/html/overload.erb +1 -1
  316. data/templates/default/tags/html/see.erb +1 -1
  317. data/templates/default/tags/html/tag.erb +1 -1
  318. data/templates/default/tags/setup.rb +4 -3
  319. data/templates/guide/fulldoc/html/css/style.css +8 -8
  320. data/templates/guide/fulldoc/html/js/app.js +6 -6
  321. data/templates/guide/fulldoc/html/setup.rb +12 -12
  322. data/templates/guide/layout/html/layout.erb +11 -11
  323. data/templates/guide/layout/html/setup.rb +9 -9
  324. data/templates/guide/method/html/header.erb +2 -2
  325. data/templates/guide/method/html/setup.rb +1 -1
  326. metadata +68 -18
  327. data/bin/yard-graph +0 -4
  328. data/bin/yard-server +0 -4
  329. data/docs/Glossary.md +0 -12
  330. data/lib/yard/handlers/ruby/legacy/macro_handler.rb +0 -39
  331. data/lib/yard/handlers/ruby/macro_handler.rb +0 -40
  332. data/lib/yard/handlers/ruby/macro_handler_methods.rb +0 -131
  333. data/lib/yard/parser/c_parser.rb +0 -497
  334. data/lib/yard/server/templates/default/layout/html/headers.erb +0 -16
  335. data/lib/yard/server/templates/doc_server/frames/html/frames.erb +0 -13
  336. data/lib/yard/server/templates/doc_server/frames/html/setup.rb +0 -3
  337. data/lib/yard/server/templates/doc_server/full_list/html/full_list.erb +0 -34
  338. data/lib/yard/server/templates/doc_server/full_list/html/setup.rb +0 -20
  339. data/spec/handlers/examples/macro_handler_001.rb.txt +0 -83
@@ -5,44 +5,20 @@ module YARD
5
5
  class ListCommand < LibraryCommand
6
6
  include Templates::Helpers::BaseHelper
7
7
 
8
- def items; raise NotImplementedError end
9
- def type; raise NotImplementedError end
10
-
11
8
  def run
12
- options.update(:items => items, :template => :doc_server,
13
- :list_type => request.path.split('/').last, :type => :full_list)
14
- render
15
- end
16
- end
17
-
18
- # Returns the list of classes / modules in a library
19
- class ListClassesCommand < ListCommand
20
- def type; :class end
21
-
22
- def items
23
9
  Registry.load_all
24
- run_verifier(Registry.all(:class, :module))
10
+ options.update(:objects => run_verifier(Registry.all(:class, :module)))
11
+ list_type = request.path.split('/').last
12
+ meth = "generate_#{list_type}_list"
13
+ tpl = fulldoc_template
14
+ if tpl.respond_to?(meth)
15
+ tpl.send(meth)
16
+ cache(tpl.contents)
17
+ else
18
+ not_found
19
+ end
25
20
  end
26
21
  end
27
-
28
- # Returns the list of methods in a library
29
- class ListMethodsCommand < ListCommand
30
- include Templates::Helpers::ModuleHelper
31
-
32
- def type; :methods end
33
-
34
- def items
35
- Registry.load_all
36
- items = Registry.all(:method).sort_by {|m| m.name.to_s }
37
- prune_method_listing(items)
38
- end
39
- end
40
-
41
- # Returns the list of README/extra files in a library
42
- class ListFilesCommand < ListCommand
43
- def type; :files end
44
- def items; options[:files] end
45
- end
46
22
  end
47
23
  end
48
24
  end
@@ -6,6 +6,7 @@ module YARD
6
6
  class SearchCommand < LibraryCommand
7
7
  include Templates::Helpers::BaseHelper
8
8
  include Templates::Helpers::ModuleHelper
9
+ include DocServerHelper
9
10
 
10
11
  attr_accessor :results, :query
11
12
 
@@ -14,7 +15,7 @@ module YARD
14
15
  self.query = request.query['q']
15
16
  redirect("/#{adapter.router.docs_prefix}/#{single_library ? library : ''}") if query.nil? || query =~ /\A\s*\Z/
16
17
  if found = Registry.at(query)
17
- redirect(serializer.serialized_path(found))
18
+ redirect(url_for(found))
18
19
  end
19
20
  search_for_object
20
21
  request.xhr? ? serve_xhr : serve_normal
@@ -26,13 +27,18 @@ module YARD
26
27
 
27
28
  private
28
29
 
30
+ def url_for(object)
31
+ File.join('', base_path(router.docs_prefix),
32
+ serializer.serialized_path(object))
33
+ end
34
+
29
35
  def serve_xhr
30
36
  self.headers['Content-Type'] = 'text/plain'
31
37
  self.body = visible_results.map {|o|
32
38
  [(o.type == :method ? o.name(true) : o.name).to_s,
33
39
  o.path,
34
40
  o.namespace.root? ? '' : o.namespace.path,
35
- serializer.serialized_path(o)
41
+ url_for(o)
36
42
  ].join(",")
37
43
  }.join("\n")
38
44
  end
@@ -9,9 +9,11 @@ module YARD
9
9
  # @return (see Templates::Helpers::HtmlHelper#url_for)
10
10
  def url_for(obj, anchor = nil, relative = false)
11
11
  return '' if obj.nil?
12
+ return url_for_index if obj == '_index.html'
12
13
  return "/#{obj}" if String === obj
13
14
  File.join('', base_path(router.docs_prefix), super(obj, anchor, false))
14
15
  end
16
+
15
17
  # Modifies {Templates::Helpers::HtmlHelper#url_for_file} to return a URL instead
16
18
  # of a disk location.
17
19
  # @param (see Templates::Helpers::HtmlHelper#url_for_file)
@@ -24,6 +26,38 @@ module YARD
24
26
  (anchor ? "##{anchor}" : "")
25
27
  end
26
28
 
29
+ # Modifies {Templates::Helpers::HtmlHelper#url_for_list} to return a URL
30
+ # based on the list prefix instead of a HTML filename.
31
+ # @param (see Templates::Helpers::HtmlHelper#url_for_list)
32
+ # @return (see Templates::Helpers::HtmlHelper#url_for_list)
33
+ def url_for_list(type)
34
+ File.join('', base_path(router.list_prefix), type.to_s)
35
+ end
36
+
37
+ # Returns the frames URL for the page
38
+ # @return (see Templates::Helpers::HtmlHelper#url_for_frameset)
39
+ def url_for_frameset
40
+ url = options.file ? url_for_file(options.file) : url_for(object)
41
+ url = url.gsub(%r{^/#{base_path(router.docs_prefix)}/}, '')
42
+ File.join('', base_path(router.docs_prefix), "frames", url)
43
+ end
44
+
45
+ # Returns the main URL, first checking a readme and then linking to the index
46
+ # @return (see Templates::Helpers::HtmlHelper#url_for_main)
47
+ def url_for_main
48
+ if options.frames && !options.command.path.empty?
49
+ File.join('', base_path(router.docs_prefix), options.command.path)
50
+ else
51
+ options.readme ? url_for_file(options.readme) : url_for_index
52
+ end
53
+ end
54
+
55
+ # Returns the URL for the alphabetic index page
56
+ # @return (see Templates::Helpers::HtmlHelper#url_for_index)
57
+ def url_for_index
58
+ File.join('', base_path(router.docs_prefix), 'index')
59
+ end
60
+
27
61
  # @example The base path for a library 'foo'
28
62
  # base_path('docs') # => 'docs/foo'
29
63
  # @param [String] path the path prefix for a base path URI
@@ -44,11 +44,15 @@ module YARD
44
44
  include WEBrick::HTTPUtils
45
45
 
46
46
  # Responds to Rack requests and builds a response with the {Router}.
47
- # @return [Array(Number,Hash,Array)] the Rack-style response
47
+ # @return [Array(Numeric,Hash,Array)] the Rack-style response
48
48
  def call(env)
49
49
  request = Rack::Request.new(env)
50
50
  request.path_info = unescape(request.path_info) # unescape things like %3F
51
51
  router.call(request)
52
+ rescue StandardError => ex
53
+ log.backtrace(ex)
54
+ [500, {'Content-Type' => 'text/plain'},
55
+ [ex.message + "\n" + ex.backtrace.join("\n")]]
52
56
  end
53
57
 
54
58
  # Starts the +Rack::Server+. This method will pass control to the server and
@@ -48,7 +48,7 @@ module YARD
48
48
  # file through {Commands::StaticFileCommand} if no route is found.
49
49
  #
50
50
  # @param [Adapter Dependent] request the request object
51
- # @return [Array(Number,Hash,Array)] the Rack-style server response data
51
+ # @return [Array(Numeric,Hash,Array)] the Rack-style server response data
52
52
  def call(request)
53
53
  self.request = request
54
54
  if result = (check_static_cache || route)
@@ -97,8 +97,8 @@ module YARD
97
97
  #
98
98
  # @return [Array(Numeric,Hash,Array<String>)] the Rack-style response
99
99
  # @return [nil] if no route is matched
100
- def route
101
- path = request.path.gsub(%r{//+}, '/').gsub(%r{^/|/$}, '')
100
+ def route(path = request.path)
101
+ path = path.gsub(%r{//+}, '/').gsub(%r{^/|/$}, '')
102
102
  return route_index if path.empty? || path == docs_prefix
103
103
  case path
104
104
  when /^(#{docs_prefix}|#{list_prefix}|#{search_prefix})(\/.*|$)/
@@ -150,13 +150,7 @@ module YARD
150
150
  # @return (see #route_docs)
151
151
  def route_list(library, paths)
152
152
  return if paths.empty?
153
- case paths.shift
154
- when "class"; cmd = ListClassesCommand
155
- when "methods"; cmd = ListMethodsCommand
156
- when "files"; cmd = ListFilesCommand
157
- else; return
158
- end
159
- cmd.new(final_options(library, paths)).call(request)
153
+ ListCommand.new(final_options(library, paths)).call(request)
160
154
  end
161
155
 
162
156
  # Routes requests from {#search_prefix} and calls the appropriate command
@@ -27,7 +27,7 @@ module YARD
27
27
  # end
28
28
  #
29
29
  # class YARD::Server::Router; include MemoryCaching; end
30
- # @return [Array(Number,Hash,Array)] the Rack-style response
30
+ # @return [Array(Numeric,Hash,Array)] the Rack-style response
31
31
  # @return [nil] if no cache is available and routing should continue
32
32
  # @see Commands::Base#cache
33
33
  def check_static_cache
@@ -42,4 +42,4 @@ module YARD
42
42
  end
43
43
  end
44
44
  end
45
- end
45
+ end
@@ -49,11 +49,11 @@ form.search input { margin-left: 5px; width: 250px; border: 1px solid #99f; -moz
49
49
  font-size: 12px;
50
50
  line-height: 16px;
51
51
  overflow: hidden;
52
-
52
+
53
53
  }
54
54
 
55
55
  .ac_loading {
56
- background: white url('/images/loading.gif') right center no-repeat;
56
+ background: white url('/images/processing.gif') right center no-repeat;
57
57
  }
58
58
 
59
59
  .ac_even {
@@ -1,17 +1,3 @@
1
- function searchFrameLinks() {
2
- $('#method_list_link').unbind("click").click(function() {
3
- toggleSearchFrame(this, '/' + library + '/methods');
4
- });
5
-
6
- $('#class_list_link').unbind("click").click(function() {
7
- toggleSearchFrame(this, '/' + library + '/class');
8
- });
9
-
10
- $('#file_list_link').unbind("click").click(function() {
11
- toggleSearchFrame(this, '/' + library + '/files');
12
- });
13
- }
14
-
15
1
  function methodPermalinks() {
16
2
  if ($($('#content h1')[0]).text().match(/^Method:/)) return;
17
3
 
@@ -28,5 +14,4 @@ function methodPermalinks() {
28
14
  });
29
15
  }
30
16
 
31
- $(searchFrameLinks);
32
17
  $(methodPermalinks);
@@ -3,7 +3,7 @@
3
3
  </form>
4
4
  <script type="text/javascript" charset="utf-8">
5
5
  $(function() {
6
- $('#search_box').autocomplete('/<%= base_path(router.search_prefix) %>', {
6
+ $('#search_box').autocomplete($('#search_box').parent().attr('action'), {
7
7
  width: document.body.className == 'frames' ? 250 : 340,
8
8
  formatItem: function(item) {
9
9
  var values = item[0].split(",");
@@ -31,13 +31,13 @@
31
31
  <% end %>
32
32
  <% if object.is_a?(CodeObjects::Base) && @file.nil? %>
33
33
  <% unless @single_library %>&raquo;<% end %>
34
- <a href="/<%= base_path(router.docs_prefix) %>"><% if object.root? || object.type == :method %>Index<% else %>Index (<%= object.name.to_s[0] %>)<% end %></a> &raquo;
34
+ <a href="<%= url_for_index %>"><% if object.root? || object.type == :method %>Index<% else %>Index (<%= object.name.to_s[0] %>)<% end %></a> &raquo;
35
35
  <%= @breadcrumb.map {|obj| "<span class='title'>" + linkify(obj, obj.name) + "</span>" }.join(" &raquo; ") %>
36
36
  <%= @breadcrumb.size > 0 ? " &raquo; " : "" %>
37
37
  <span class='title'><%= object.root? ? "Top Level Namespace" : object.name(true) %></span>
38
38
  <% else %>
39
39
  <% if (@breadcrumb_title || object != '_index.html') && !@single_library %>&raquo; <% end %>
40
- <% if object != '_index.html' %><a href="/<%= base_path(router.docs_prefix) %>">Index</a> &raquo; <% end %>
40
+ <% if object != '_index.html' %><a href="<%= url_for_index %>">Index</a> &raquo; <% end %>
41
41
  <span class='title'><%= @breadcrumb_title %></span>
42
42
  <% end %>
43
43
 
@@ -0,0 +1,8 @@
1
+ <script type="text/javascript" charset="utf-8">
2
+ hasFrames = window.top.frames.main ? true : false;
3
+ relpath = '/';
4
+ docsPrefix = '<%= base_path(router.docs_prefix) %>';
5
+ listPrefix = '<%= base_path(router.list_prefix) %>';
6
+ searchPrefix = '<%= base_path(router.search_prefix) %>';
7
+ framesUrl = '<%= url_for_frameset %>';
8
+ </script>
@@ -8,7 +8,7 @@
8
8
  <script type="text/javascript" charset="utf-8" src="/js/jquery.js"></script>
9
9
  <script type="text/javascript" charset="utf-8">
10
10
  function checkPage(process) {
11
- $.ajax({cache: false, url: "<%= @path %>" + (process ? "?process=true" : ""), statusCode: { 200: function() { window.location = "<%= @path %>"; } } });
11
+ $.ajax({cache: false, url: "<%= router.request.path %>" + (process ? "?process=true" : ""), statusCode: { 200: function() { window.location = "<%= @path %>"; } } });
12
12
  setTimeout('checkPage()', 2000);
13
13
  }
14
14
  function setFade() {
@@ -3,6 +3,6 @@ def init
3
3
  end
4
4
 
5
5
  def search
6
- options[:breadcrumb_title] = h("Search for '#{@query}'")
6
+ options.breadcrumb_title = h("Search for '#{@query}'")
7
7
  yieldall :contents => erb(:search)
8
8
  end
@@ -47,6 +47,24 @@ module YARD
47
47
  Tag.new(tag_name, text, types, name)
48
48
  end
49
49
 
50
+ # Parses tag text and creates a new tag with formally declared types, a title
51
+ # on the first line and descriptive text
52
+ #
53
+ # @param tag_name the name of the tag to parse
54
+ # @param [String] text the raw tag text
55
+ # @return [Tag] a tag object with the tag_name, name, types and text values filled
56
+ def parse_tag_with_types_and_title(tag_name, text)
57
+ name, types, text = *extract_types_and_name_from_text_unstripped(text)
58
+ if name
59
+ title, desc = name, text
60
+ else
61
+ title, desc = *extract_title_and_desc_from_text(text)
62
+ end
63
+ Tag.new(tag_name, desc, types, title)
64
+ rescue TagFormatError
65
+ Tag.new(tag_name, '', types, nil)
66
+ end
67
+
50
68
  def parse_tag_with_title_and_text(tag_name, text)
51
69
  title, desc = *extract_title_and_desc_from_text(text)
52
70
  Tag.new(tag_name, desc, nil, title)
@@ -105,6 +123,15 @@ module YARD
105
123
  # list (or nil), followed by the type list parsed into an array of
106
124
  # strings, followed by the text following the type list.
107
125
  def extract_types_and_name_from_text(text, opening_types = TYPELIST_OPENING_CHARS, closing_types = TYPELIST_CLOSING_CHARS)
126
+ before, list, text = *extract_types_and_name_from_text_unstripped(text, opening_types, closing_types)
127
+ if list.nil?
128
+ [nil, nil, text.strip]
129
+ else
130
+ [before ? before.strip : nil, list.map {|e| e.strip }, text.strip]
131
+ end
132
+ end
133
+
134
+ def extract_types_and_name_from_text_unstripped(text, opening_types = TYPELIST_OPENING_CHARS, closing_types = TYPELIST_CLOSING_CHARS)
108
135
  s, e = 0, 0
109
136
  before = ''
110
137
  list, level, seen_space = [''], 0, false
@@ -114,7 +141,7 @@ module YARD
114
141
  s = i if level == 0
115
142
  level += 1
116
143
  elsif closing_types.include?(c)
117
- level -= 1 unless list.last[-1,1] == '='
144
+ level -= 1 unless list.last[-1,1] == '=' && c == '>'
118
145
  break e = i if level == 0
119
146
  list.last << c
120
147
  elsif c == ',' && level == 1
@@ -129,11 +156,11 @@ module YARD
129
156
  end
130
157
  end
131
158
 
132
- before = before.empty? ? nil : before.strip
159
+ before = before.empty? ? nil : before
133
160
  if list.size == 1 && list.first == ''
134
- [nil, nil, text.strip]
161
+ [nil, nil, text]
135
162
  else
136
- [before, list.map {|x| x.strip }, text[(e+1)..-1].strip]
163
+ [before, list, text[(e+1)..-1]]
137
164
  end
138
165
  end
139
166
  end
@@ -0,0 +1,593 @@
1
+ require 'ostruct'
2
+
3
+ module YARD
4
+ module Tags
5
+ # The base directive class. Subclass this class to create a custom
6
+ # directive, registering it with {Library.define_directive}. Directive
7
+ # classes are executed via the {#call} method, which perform all directive
8
+ # processing on the object.
9
+ #
10
+ # If processing occurs within a handler, the {#handler} attribute is
11
+ # available to access more information about parsing context and state.
12
+ # Handlers are only available when parsing from {Parser::SourceParser},
13
+ # not when parsing directly from {DocstringParser}. If the docstring is
14
+ # attached to an object declaration, {#object} will be set and available
15
+ # to modify the generated code object directly. Note that both of these
16
+ # attributes may be nil, and directives should test their existence
17
+ # before attempting to use them.
18
+ #
19
+ # @abstract Subclasses should implement {#call}.
20
+ # @see Library.define_directive
21
+ # @since 0.8.0
22
+ class Directive
23
+ # @return [Tag] the meta-data tag containing data input to the directive
24
+ attr_accessor :tag
25
+
26
+ # Set this field to replace the directive definition inside of a docstring
27
+ # with arbitrary text. For instance, the {MacroDirective} uses this field
28
+ # to expand its macro data in place of the call to a +@!macro+.
29
+ #
30
+ # @return [String] the text to expand in the original docstring in place
31
+ # of this directive definition.
32
+ # @return [nil] if no expansion should take place for this directive
33
+ attr_accessor :expanded_text
34
+
35
+ # @return [DocstringParser] the parser that is parsing all tag
36
+ # information out of the docstring
37
+ attr_accessor :parser
38
+
39
+ # @!attribute [r] object
40
+ # @return [CodeObjects::Base, nil] the object the parent docstring is
41
+ # attached to. May be nil.
42
+ def object; parser.object end
43
+
44
+ # @!attribute [r] handler
45
+ # @return [Handlers::Base, nil] the handler object the docstring parser
46
+ # might be attached to. May be nil. Only available when parsing
47
+ # through {Parser::SourceParser}.
48
+ def handler; parser.handler end
49
+
50
+ # @!endgroup
51
+
52
+ # @param [Tag] tag the meta-data tag containing all input to the docstring
53
+ # @param [DocstringParser] parser the docstring parser object
54
+ def initialize(tag, parser)
55
+ self.tag = tag
56
+ self.parser = parser
57
+ self.expanded_text = nil
58
+ end
59
+
60
+ # @!group Parser callbacks
61
+
62
+ # Called when processing the directive. Subclasses should implement
63
+ # this method to perform all functionality of the directive.
64
+ #
65
+ # @abstract implement this method to perform all data processing for
66
+ # the directive.
67
+ # @return [void]
68
+ def call; raise NotImplementedError end
69
+
70
+ # Called after parsing all directives and tags in the docstring. Used
71
+ # to perform any cleanup after all directives perform their main task.
72
+ # @return [void]
73
+ def after_parse; end
74
+
75
+ protected :parser
76
+ end
77
+
78
+ # Ends a group listing definition. Group definition automatically end
79
+ # when class or module blocks are closed, and defining a new group overrides
80
+ # the last group definition, but occasionally you need to end the current
81
+ # group to return to the default listing. Use {tag:!group} to begin a
82
+ # group listing.
83
+ #
84
+ # @example
85
+ # class Controller
86
+ # # @!group Callbacks
87
+ #
88
+ # def before_filter; end
89
+ # def after_filter; end
90
+ #
91
+ # # @!endgroup
92
+ #
93
+ # def index; end
94
+ # end
95
+ # @see tag:!group
96
+ # @since 0.6.0
97
+ class EndGroupDirective < Directive
98
+ def call
99
+ return unless handler
100
+ handler.extra_state.group = nil
101
+ end
102
+ end
103
+
104
+ # Defines a group listing. All methods (and attributes) seen after this
105
+ # directive are placed into a group with the given description as the
106
+ # group name. The group listing is used by templates to organize methods
107
+ # and attributes into respective logical groups. To end a group listing
108
+ # use {tag:!endgroup}.
109
+ #
110
+ # @note A group definition only applies to the scope it is defined in.
111
+ # If a new class or module is opened after the directive, this directive
112
+ # will not apply to methods in that class or module.
113
+ # @example
114
+ # # @!group Callbacks
115
+ #
116
+ # def before_filter; end
117
+ # def after_filter; end
118
+ # @see tag:!endgroup
119
+ # @since 0.6.0
120
+ class GroupDirective < Directive
121
+ def call
122
+ return unless handler
123
+ handler.extra_state.group = tag.text
124
+ end
125
+ end
126
+
127
+ # Defines a block of text to be expanded whenever the macro is called by name
128
+ # in subsequent docstrings. The macro data can be any arbitrary text data, be
129
+ # it regular documentation, meta-data tags or directives.
130
+ #
131
+ # == Defining a Macro
132
+ #
133
+ # A macro must first be defined in order to be used. Note that a macro is also
134
+ # expanded upon definition if it defined on an object (the docstring of a
135
+ # method, class, module or constant object as opposed to a free standing
136
+ # comment). To define a macro, use the "new" or "attach" identifier in the
137
+ # types specifier list. A macro will also automatically be created if an
138
+ # indented macro data block is given, so the keywords are not strictly needed.
139
+ #
140
+ # === Anonymous Macros
141
+ #
142
+ # In addition to standard named macros, macros can be defined anonymously if
143
+ # no name is given. In this case, they can not be re-used in future docstrings,
144
+ # but they will expand in the first definition. This is useful when needing
145
+ # to take advantage of the macro expansion variables (described below).
146
+ #
147
+ # == Using a Macro
148
+ #
149
+ # To re-use a macro in another docstring after it is defined, simply use
150
+ # <tt>@!macro the_name</tt> with no indented block of macro data. The resulting
151
+ # data will be expanded in place.
152
+ #
153
+ # == Attaching a Macro to a DSL Method
154
+ #
155
+ # Macros can be defined to auto-expand on DSL-style class method calls. To
156
+ # define a macro to be auto expanded in this way, use the "attach" keyword
157
+ # in the type specifier list ("new" is implied).
158
+ #
159
+ # Attached macros can also be attached directly on the class method declaration
160
+ # that provides the DSL method to its subclasses. The syntax in either case
161
+ # is the same.
162
+ #
163
+ # == Macro Expansion Variables
164
+ #
165
+ # In the case of using macros on DSL-style method calls, a number of expansion
166
+ # variables can be used for interpolation inside of the macro data. The variables,
167
+ # similar in syntax to Ruby's global variables, are as follows:
168
+ #
169
+ # * $0 - the method name being called
170
+ # * $1, $2, $3, ... - the Nth argument in the method call
171
+ # * $& - the full source line
172
+ #
173
+ # The following example shows what the expansion variables might hold for a given
174
+ # DSL method call:
175
+ #
176
+ # property :foo, :a, :b, :c, String
177
+ # # $0 => "property"
178
+ # # $1 => "foo"
179
+ # # $2 => "a"
180
+ # # $& => "property :foo, :a, :b, :c, String"
181
+ #
182
+ # === Ranges
183
+ #
184
+ # Ranges are also acceptable with the syntax <tt>${N-M}</tt>. Negative values
185
+ # on either N or M are valid, and refer to indexes from the end of the list.
186
+ # Consider a DSL method that creates a method using the first argument with
187
+ # argument names following, ending with the return type of the method. This
188
+ # could be documented as:
189
+ #
190
+ # # @!macro dsl_method
191
+ # # @!method $1(${2--2})
192
+ # # @return [${-1}] the return value of $0
193
+ # create_method_with_args :foo, :a, :b, :c, String
194
+ #
195
+ # As described, the method is using the signature <tt>foo(a, b, c)</tt> and the return
196
+ # type from the last argument, +String+. When using ranges, tokens are joined
197
+ # with commas. Note that this includes using $0:
198
+ #
199
+ # !!!plain
200
+ # $0-1 # => Interpolates to "create_method_with_args, foo"
201
+ #
202
+ # If you want to separate them with spaces, use <tt>$1 $2 $3 $4 ...</tt>. Note that
203
+ # if the token cannot be expanded, it will return the empty string (not an error),
204
+ # so it would be safe to list <tt>$1 $2 ... $10</tt>, for example.
205
+ #
206
+ # === Escaping Interpolation
207
+ #
208
+ # Interpolation can be escaped by prefixing the +$+ with +\+, like so:
209
+ #
210
+ # # @!macro foo
211
+ # # I have \$2.00 USD.
212
+ #
213
+ # @example Defining a simple macro
214
+ # # @!macro [new] returnself
215
+ # # @return [self] returns itself
216
+ # @example Using a simple macro in multiple docstrings
217
+ # # Documentation for map
218
+ # # ...
219
+ # # @macro returnself
220
+ # def map; end
221
+ #
222
+ # # Documentation for filter
223
+ # # ...
224
+ # # @macro returnself
225
+ # def filter; end
226
+ # @example Attaching a macro to a class method (for DSL usage)
227
+ # class Resource
228
+ # # Defines a new property
229
+ # # @param [String] name the property name
230
+ # # @param [Class] type the property's type
231
+ # # @!macro [attach] property
232
+ # # @return [$2] the $1 property
233
+ # def self.property(name, type) end
234
+ # end
235
+ #
236
+ # class Post < Resource
237
+ # property :title, String
238
+ # property :view_count, Integer
239
+ # end
240
+ # @example Attaching a macro directly to a DSL method
241
+ # class Post < Resource
242
+ # # @!macro [attach] property
243
+ # # @return [$2] the $1 property
244
+ # property :title, String
245
+ #
246
+ # # Macro will expand on this definition too
247
+ # property :view_count, Integer
248
+ # end
249
+ # @since 0.7.0
250
+ class MacroDirective < Directive
251
+ def call
252
+ raise TagFormatError if tag.name.nil? && tag.text.to_s.empty?
253
+ unless macro_data = find_or_create
254
+ warn
255
+ return
256
+ end
257
+
258
+ self.expanded_text = expand(macro_data)
259
+ end
260
+
261
+ private
262
+
263
+ def new?
264
+ (tag.types && tag.types.include?('new')) ||
265
+ (tag.text && !tag.text.strip.empty?)
266
+ end
267
+
268
+ def attach?
269
+ class_method? || # always attach to class methods
270
+ (tag.types && tag.types.include?('attach'))
271
+ end
272
+
273
+ def class_method?
274
+ object && object.is_a?(CodeObjects::MethodObject) &&
275
+ object.scope == :class
276
+ end
277
+
278
+ def anonymous?
279
+ tag.name.nil? || tag.name.empty?
280
+ end
281
+
282
+ def expand(macro_data)
283
+ return if attach? && class_method?
284
+ return if !anonymous? && new? &&
285
+ (!handler || handler.statement.source.empty?)
286
+ call_params = []
287
+ caller_method = nil
288
+ full_source = ''
289
+ if handler
290
+ call_params = handler.call_params
291
+ caller_method = handler.caller_method
292
+ full_source = handler.statement.source
293
+ end
294
+ all_params = ([caller_method] + call_params).compact
295
+ CodeObjects::MacroObject.expand(macro_data, all_params, full_source)
296
+ end
297
+
298
+ def find_or_create
299
+ if new? || attach?
300
+ if handler && attach?
301
+ obj = object ? object :
302
+ P("#{handler.namespace}.#{handler.caller_method}")
303
+ else
304
+ obj = nil
305
+ end
306
+ if anonymous? # anonymous macro
307
+ return tag.text || ""
308
+ else
309
+ macro = CodeObjects::MacroObject.create(tag.name, tag.text, obj)
310
+ end
311
+ else
312
+ macro = CodeObjects::MacroObject.find(tag.name)
313
+ end
314
+
315
+ macro ? macro.macro_data : nil
316
+ end
317
+
318
+ def warn
319
+ if object && handler
320
+ log.warn "Invalid/missing macro name for " +
321
+ "#{object.path} (#{handler.parser.file}:#{handler.statement.line})"
322
+ end
323
+ end
324
+ end
325
+
326
+ # Defines a method object with a given method signature, using indented
327
+ # block data as the method's docstring. The signature is similar to the
328
+ # {tag:overload} tag. The comment containing this directive does not need
329
+ # to be attached to any source, but if it is, that source code will be
330
+ # used as the method's source.
331
+ #
332
+ # To define an attribute method, see {tag:!attribute}
333
+ #
334
+ # @note For backwards compatibility support, you do not need to indent
335
+ # the method's docstring text. If a +@!method+ directive is seen with
336
+ # no indented block, the entire docstring is used as the new method's
337
+ # docstring text.
338
+ # @example Defining a simple method
339
+ # # @!method quit(username, message = "Quit")
340
+ # # Sends a quit message to the server for a +username+.
341
+ # # @param [String] username the username to quit
342
+ # # @param [String] message the quit message
343
+ # quit_message_method
344
+ # @example Attaching multiple methods to the same source
345
+ # # @!method method1
346
+ # # @!method method2
347
+ # create_methods :method1, :method2
348
+ # @see tag:!attribute
349
+ # @since 0.7.0
350
+ class MethodDirective < Directive
351
+ SCOPE_MATCH = /\A\s*self\s*\.\s*/
352
+
353
+ def call; end
354
+
355
+ def after_parse
356
+ return unless handler
357
+ use_indented_text
358
+ create_object
359
+ end
360
+
361
+ protected
362
+
363
+ def method_name
364
+ sig = sanitized_tag_signature
365
+ if sig && sig =~ /^#{CodeObjects::METHODNAMEMATCH}(\s|\(|$)/
366
+ sig[/\A\s*([^\(; \t]+)/, 1]
367
+ else
368
+ handler.call_params.first
369
+ end
370
+ end
371
+
372
+ def method_signature
373
+ "def #{sanitized_tag_signature || method_name}"
374
+ end
375
+
376
+ def sanitized_tag_signature
377
+ if tag.name && tag.name =~ SCOPE_MATCH
378
+ parser.state.scope = :class
379
+ $'
380
+ else
381
+ tag.name
382
+ end
383
+ end
384
+
385
+ def use_indented_text
386
+ return if tag.text.empty?
387
+ handler = parser.handler
388
+ object = parser.object
389
+ self.parser = DocstringParser.new(parser.library)
390
+ parser.parse(tag.text, object, handler)
391
+ end
392
+
393
+ def create_object
394
+ name = method_name
395
+ scope = parser.state.scope || handler.scope
396
+ visibility = parser.state.visibility || handler.visibility
397
+ ns = CodeObjects::NamespaceObject === object ? object : handler.namespace
398
+ obj = CodeObjects::MethodObject.new(ns, name, scope)
399
+ handler.register_file_info(obj)
400
+ handler.register_source(obj)
401
+ handler.register_visibility(obj, visibility)
402
+ handler.register_group(obj)
403
+ obj.signature = method_signature
404
+ obj.docstring = Docstring.new!(parser.text, parser.tags, obj,
405
+ parser.raw_text)
406
+ handler.register_module_function(obj)
407
+ obj
408
+ end
409
+ end
410
+
411
+ # Defines an attribute with a given name, using indented block data as the
412
+ # attribute's docstring. If the type specifier is supplied with "r", "w", or
413
+ # "rw", the attribute is made readonly, writeonly or readwrite respectively.
414
+ # A readwrite attribute is the default, if no type is specified. The comment
415
+ # containing this directive does not need to be attached to any source, but
416
+ # if it is, that source code will be used as the method's source.
417
+ #
418
+ # To define an regular method, see {tag:!method}
419
+ #
420
+ # @note For backwards compatibility support, you do not need to indent
421
+ # the attribute's docstring text. If an +@!attribute+ directive is seen with
422
+ # no indented block, the entire docstring is used as the new attribute's
423
+ # docstring text.
424
+ # @example Defining a simple readonly attribute
425
+ # # @!attribute [r] count
426
+ # # @return [Fixnum] the size of the list
427
+ # @example Defining a simple readwrite attribute
428
+ # # @!attribute name
429
+ # # @return [String] the name of the user
430
+ # @see tag:!method
431
+ # @since 0.7.0
432
+ class AttributeDirective < MethodDirective
433
+ def after_parse
434
+ return unless handler
435
+ use_indented_text
436
+ create_attribute_data(create_object)
437
+ end
438
+
439
+ protected
440
+
441
+ def method_name
442
+ name = sanitized_tag_signature || handler.call_params.first
443
+ name += '=' unless readable?
444
+ name
445
+ end
446
+
447
+ def method_signature
448
+ if readable?
449
+ "def #{method_name}"
450
+ else
451
+ "def #{method_name}(value)"
452
+ end
453
+ end
454
+
455
+ private
456
+
457
+ def create_attribute_data(object)
458
+ return unless object
459
+ clean_name = object.name.to_s.sub(/=$/, '')
460
+ attrs = object.namespace.attributes[object.scope]
461
+ attrs[clean_name] ||= SymbolHash[:read => nil, :write => nil]
462
+ if readable?
463
+ attrs[clean_name][:read] = object
464
+ end
465
+ if writable?
466
+ if object.name.to_s[-1,1] == '='
467
+ writer = object
468
+ writer.parameters = [['value', nil]]
469
+ else
470
+ writer = CodeObjects::MethodObject.new(object.namespace,
471
+ object.name.to_s + '=', object.scope)
472
+ writer.signature = "def #{object.name}=(value)"
473
+ writer.visibility = object.visibility
474
+ writer.dynamic = object.dynamic
475
+ writer.source = object.source
476
+ writer.group = object.group
477
+ writer.parameters = [['value', nil]]
478
+ handler.register_file_info(writer)
479
+ end
480
+ attrs[clean_name][:write] = writer
481
+ end
482
+ end
483
+
484
+ def writable?
485
+ !tag.types || tag.types.join.include?('w')
486
+ end
487
+
488
+ def readable?
489
+ !tag.types || tag.types.join =~ /(?!w)r/
490
+ end
491
+ end
492
+
493
+ # Parses a block of code as if it were present in the source file at that
494
+ # location. This directive is useful if a class has dynamic meta-programmed
495
+ # behaviour that cannot be recognized by YARD.
496
+ #
497
+ # You can specify the language of the code block using the types
498
+ # specification list. By default, the code language is "ruby".
499
+ #
500
+ # @example Documenting dynamic module inclusion
501
+ # class User
502
+ # # includes "UserMixin" and extends "UserMixin::ClassMethods"
503
+ # # using the UserMixin.included callback.
504
+ # # @!parse include UserMixin
505
+ # # @!parse extend UserMixin::ClassMethods
506
+ # end
507
+ # @example Declaring a method as an attribute
508
+ # # This should really be an attribute
509
+ # # @!parse attr_reader :foo
510
+ # def object; @parent.object end
511
+ # @example Parsing C code
512
+ # # @!parse [c]
513
+ # # void Init_Foo() {
514
+ # # rb_define_method(rb_cFoo, "method", method, 0);
515
+ # # }
516
+ # @since 0.8.0
517
+ class ParseDirective < Directive
518
+ def call
519
+ lang = tag.types ? tag.types.first.to_sym :
520
+ (handler ? handler.parser.parser_type : :ruby)
521
+ if handler && lang == handler.parser.parser_type
522
+ pclass = Parser::SourceParser.parser_types[handler.parser.parser_type]
523
+ pobj = pclass.new(tag.text, handler.parser.file)
524
+ pobj.parse
525
+ handler.parser.process(pobj.enumerator)
526
+ else # initialize a new parse chain
527
+ src_parser = Parser::SourceParser.new(lang, handler ? handler.globals : nil)
528
+ src_parser.file = handler.parser.file if handler
529
+ src_parser.parse(StringIO.new(tag.text))
530
+ end
531
+ end
532
+ end
533
+
534
+ # Modifies the current parsing scope (class or instance). If this
535
+ # directive is defined on a docstring attached to an object definition,
536
+ # it is applied only to that object. Otherwise, it applies the scope
537
+ # to all future objects in the namespace.
538
+ #
539
+ # @example Modifying the scope of a DSL method
540
+ # # @!scope class
541
+ # cattr_accessor :subclasses
542
+ # @example Modifying the scope of a set of methods
543
+ # # @!scope class
544
+ #
545
+ # # Documentation for method1
546
+ # def method1; end
547
+ #
548
+ # # Documentation for method2
549
+ # def method2; end
550
+ # @since 0.7.0
551
+ class ScopeDirective < Directive
552
+ def call
553
+ if %w(class instance module).include?(tag.text)
554
+ if object.is_a?(CodeObjects::MethodObject)
555
+ object.scope = tag.text.to_sym
556
+ else
557
+ parser.state.scope = tag.text.to_sym
558
+ end
559
+ end
560
+ end
561
+ end
562
+
563
+ # Modifies the current parsing visibility (public, protected, or private).
564
+ # If this directive is defined on a docstring attached to an object
565
+ # definition, it is applied only to that object. Otherwise, it applies
566
+ # the visibility to all future objects in the namespace.
567
+ #
568
+ # @example Modifying the visibility of a DSL method
569
+ # # @!visibility private
570
+ # cattr_accessor :subclasses
571
+ # @example Modifying the visibility of a set of methods
572
+ # # Note that Ruby's "protected" is recommended over this directive
573
+ # # @!visibility protected
574
+ #
575
+ # # Documentation for method1
576
+ # def method1; end
577
+ #
578
+ # # Documentation for method2
579
+ # def method2; end
580
+ # @since 0.7.0
581
+ class VisibilityDirective < Directive
582
+ def call
583
+ if %w(public protected private).include?(tag.text)
584
+ if object.is_a?(CodeObjects::Base)
585
+ object.visibility = tag.text.to_sym
586
+ else
587
+ parser.state.visibility = tag.text.to_sym
588
+ end
589
+ end
590
+ end
591
+ end
592
+ end
593
+ end