yard 0.2.1 → 0.2.2

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 (264) hide show
  1. data/{LICENSE.txt → LICENSE} +1 -1
  2. data/README +211 -0
  3. data/Rakefile +31 -0
  4. data/benchmarks/builtins_vs_eval.rb +23 -0
  5. data/benchmarks/erb_vs_erubis.rb +53 -0
  6. data/benchmarks/generation.rb +37 -0
  7. data/benchmarks/parsing.rb +33 -0
  8. data/bin/view_generator +17 -0
  9. data/bin/yard-graph +4 -0
  10. data/bin/yardoc +1 -93
  11. data/bin/yri +12 -3
  12. data/lib/yard.rb +10 -5
  13. data/lib/yard/autoload.rb +116 -0
  14. data/lib/yard/cli/yard_graph.rb +86 -0
  15. data/lib/yard/cli/yardoc.rb +131 -0
  16. data/lib/yard/code_objects/base.rb +321 -0
  17. data/lib/yard/code_objects/class_object.rb +89 -0
  18. data/lib/yard/code_objects/class_variable_object.rb +4 -0
  19. data/lib/yard/code_objects/constant_object.rb +4 -0
  20. data/lib/yard/code_objects/method_object.rb +51 -0
  21. data/lib/yard/code_objects/module_object.rb +4 -0
  22. data/lib/yard/code_objects/namespace_object.rb +88 -0
  23. data/lib/yard/code_objects/proxy.rb +183 -0
  24. data/lib/yard/code_objects/root_object.rb +8 -0
  25. data/lib/yard/core_ext/file.rb +26 -0
  26. data/lib/yard/core_ext/logger.rb +5 -0
  27. data/lib/yard/core_ext/module.rb +9 -0
  28. data/lib/yard/core_ext/string.rb +13 -0
  29. data/lib/yard/core_ext/symbol_hash.rb +24 -0
  30. data/lib/yard/generators/attributes_generator.rb +22 -0
  31. data/lib/yard/generators/base.rb +285 -0
  32. data/lib/yard/generators/class_generator.rb +25 -0
  33. data/lib/yard/generators/constants_generator.rb +73 -0
  34. data/lib/yard/generators/constructor_generator.rb +25 -0
  35. data/lib/yard/generators/deprecated_generator.rb +15 -0
  36. data/lib/yard/generators/docstring_generator.rb +15 -0
  37. data/lib/yard/generators/full_doc_generator.rb +59 -0
  38. data/lib/yard/generators/helpers/base_helper.rb +52 -0
  39. data/lib/yard/generators/helpers/filter_helper.rb +21 -0
  40. data/lib/yard/generators/helpers/html_helper.rb +137 -0
  41. data/lib/yard/generators/helpers/method_helper.rb +27 -0
  42. data/lib/yard/generators/helpers/uml_helper.rb +16 -0
  43. data/lib/yard/generators/inheritance_generator.rb +16 -0
  44. data/lib/yard/generators/method_details_generator.rb +18 -0
  45. data/lib/yard/generators/method_generator.rb +31 -0
  46. data/lib/yard/generators/method_listing_generator.rb +105 -0
  47. data/lib/yard/generators/method_missing_generator.rb +25 -0
  48. data/lib/yard/generators/method_signature_generator.rb +19 -0
  49. data/lib/yard/generators/method_summary_generator.rb +21 -0
  50. data/lib/yard/generators/mixins_generator.rb +15 -0
  51. data/lib/yard/generators/module_generator.rb +22 -0
  52. data/lib/yard/generators/quick_doc_generator.rb +31 -0
  53. data/lib/yard/generators/source_generator.rb +26 -0
  54. data/lib/yard/generators/tags_generator.rb +50 -0
  55. data/lib/yard/generators/uml_generator.rb +92 -0
  56. data/lib/yard/generators/visibility_group_generator.rb +26 -0
  57. data/lib/yard/handlers/alias_handler.rb +32 -0
  58. data/lib/yard/handlers/attribute_handler.rb +54 -0
  59. data/lib/yard/handlers/base.rb +509 -0
  60. data/lib/yard/handlers/class_handler.rb +44 -0
  61. data/lib/yard/handlers/class_variable_handler.rb +13 -0
  62. data/lib/yard/handlers/constant_handler.rb +13 -0
  63. data/lib/yard/handlers/exception_handler.rb +12 -0
  64. data/lib/yard/handlers/method_handler.rb +27 -0
  65. data/lib/yard/handlers/mixin_handler.rb +16 -0
  66. data/lib/yard/handlers/module_handler.rb +9 -0
  67. data/lib/yard/handlers/visibility_handler.rb +14 -0
  68. data/lib/yard/handlers/yield_handler.rb +26 -0
  69. data/lib/yard/logging.rb +27 -0
  70. data/lib/yard/parser/ruby_lex.rb +1344 -0
  71. data/lib/yard/parser/source_parser.rb +109 -0
  72. data/lib/yard/parser/statement.rb +36 -0
  73. data/lib/yard/parser/statement_list.rb +167 -0
  74. data/lib/yard/parser/token_list.rb +58 -0
  75. data/lib/yard/rake/yardoc_task.rb +30 -0
  76. data/lib/yard/registry.rb +136 -0
  77. data/lib/yard/serializers/base.rb +16 -0
  78. data/lib/yard/serializers/file_system_serializer.rb +48 -0
  79. data/lib/yard/serializers/process_serializer.rb +14 -0
  80. data/lib/yard/serializers/stdout_serializer.rb +21 -0
  81. data/lib/yard/tags/default_factory.rb +98 -0
  82. data/lib/yard/tags/library.rb +109 -0
  83. data/lib/yard/tags/merbdoc_factory.rb +47 -0
  84. data/lib/yard/tags/tag.rb +35 -0
  85. data/spec/code_objects/base_spec.rb +219 -0
  86. data/spec/code_objects/class_object_spec.rb +176 -0
  87. data/spec/code_objects/code_object_list_spec.rb +33 -0
  88. data/spec/code_objects/constants_spec.rb +79 -0
  89. data/spec/code_objects/method_object_spec.rb +30 -0
  90. data/spec/code_objects/module_object_spec.rb +73 -0
  91. data/spec/code_objects/namespace_object_spec.rb +129 -0
  92. data/spec/code_objects/proxy_spec.rb +80 -0
  93. data/spec/code_objects/spec_helper.rb +3 -0
  94. data/spec/core_ext/file_spec.rb +20 -0
  95. data/spec/core_ext/string_spec.rb +4 -0
  96. data/spec/core_ext/symbol_hash_spec.rb +80 -0
  97. data/spec/generators/base_spec.rb +64 -0
  98. data/spec/generators/helpers/base_helper_spec.rb +15 -0
  99. data/spec/generators/helpers/html_helper_spec.rb +56 -0
  100. data/spec/generators/quick_doc_generator_spec.rb +13 -0
  101. data/spec/handlers/alias_handler_spec.rb +50 -0
  102. data/spec/handlers/attribute_handler_spec.rb +78 -0
  103. data/spec/handlers/base_spec.rb +165 -0
  104. data/spec/handlers/class_handler_spec.rb +68 -0
  105. data/spec/handlers/class_variable_handler_spec.rb +9 -0
  106. data/spec/handlers/constant_handler_spec.rb +13 -0
  107. data/spec/handlers/examples/alias_handler_001.rb.txt +24 -0
  108. data/spec/handlers/examples/attribute_handler_001.rb.txt +19 -0
  109. data/spec/handlers/examples/class_handler_001.rb.txt +39 -0
  110. data/spec/handlers/examples/class_variable_handler_001.rb.txt +9 -0
  111. data/spec/handlers/examples/constant_handler_001.rb.txt +10 -0
  112. data/spec/handlers/examples/exception_handler_001.rb.txt +42 -0
  113. data/spec/handlers/examples/method_handler_001.rb.txt +35 -0
  114. data/spec/handlers/examples/mixin_handler_001.rb.txt +12 -0
  115. data/spec/handlers/examples/module_handler_001.rb.txt +16 -0
  116. data/spec/handlers/examples/visibility_handler_001.rb.txt +20 -0
  117. data/spec/handlers/examples/yield_handler_001.rb.txt +55 -0
  118. data/spec/handlers/exception_handler_spec.rb +35 -0
  119. data/spec/handlers/method_handler_spec.rb +35 -0
  120. data/spec/handlers/mixin_handler_spec.rb +30 -0
  121. data/spec/handlers/module_handler_spec.rb +25 -0
  122. data/spec/handlers/spec_helper.rb +21 -0
  123. data/spec/handlers/visibility_handler_spec.rb +24 -0
  124. data/spec/handlers/yield_handler_spec.rb +51 -0
  125. data/spec/parser/examples/example1.rb.txt +8 -0
  126. data/spec/parser/examples/tag_handler_001.rb.txt +8 -0
  127. data/spec/parser/source_parser_spec.rb +43 -0
  128. data/spec/parser/tag_parsing_spec.rb +18 -0
  129. data/spec/parser/token_list_spec.rb +35 -0
  130. data/spec/registry_spec.rb +70 -0
  131. data/spec/serializers/file_system_serializer_spec.rb +91 -0
  132. data/spec/serializers/spec_helper.rb +2 -0
  133. data/spec/spec_helper.rb +77 -0
  134. data/templates/default/attributes/html/header.erb +35 -0
  135. data/templates/default/attributes/text/header.erb +10 -0
  136. data/templates/default/class/html/header.erb +4 -0
  137. data/templates/default/constants/html/constants.erb +9 -0
  138. data/templates/default/constants/html/header.erb +3 -0
  139. data/templates/default/constants/html/included.erb +9 -0
  140. data/templates/default/constants/html/inherited.erb +9 -0
  141. data/templates/default/constructor/html/header.erb +10 -0
  142. data/templates/default/deprecated/html/main.erb +4 -0
  143. data/templates/default/deprecated/text/main.erb +3 -0
  144. data/templates/default/docstring/html/main.erb +3 -0
  145. data/templates/default/docstring/text/main.erb +3 -0
  146. data/templates/default/fulldoc/html/all_methods.erb +25 -0
  147. data/templates/default/fulldoc/html/all_namespaces.erb +19 -0
  148. data/templates/default/fulldoc/html/app.js +18 -0
  149. data/templates/default/fulldoc/html/header.erb +15 -0
  150. data/templates/default/fulldoc/html/html_head.erb +3 -0
  151. data/templates/default/fulldoc/html/index.erb +18 -0
  152. data/templates/default/fulldoc/html/jquery.js +11 -0
  153. data/templates/default/fulldoc/html/readme.erb +15 -0
  154. data/templates/default/fulldoc/html/style.css +65 -0
  155. data/templates/default/fulldoc/html/syntax_highlight.css +21 -0
  156. data/templates/default/inheritance/html/header.erb +8 -0
  157. data/templates/default/inheritance/text/header.erb +3 -0
  158. data/templates/default/method/html/aliases.erb +6 -0
  159. data/templates/default/method/html/header.erb +3 -0
  160. data/templates/default/method/html/title.erb +3 -0
  161. data/templates/default/methoddetails/html/header.erb +8 -0
  162. data/templates/default/methoddetails/html/method_header.erb +3 -0
  163. data/templates/default/methodmissing/html/header.erb +12 -0
  164. data/templates/default/methodsignature/html/main.erb +8 -0
  165. data/templates/default/methodsignature/text/main.erb +5 -0
  166. data/templates/default/methodsummary/html/header.erb +5 -0
  167. data/templates/default/methodsummary/html/included.erb +9 -0
  168. data/templates/default/methodsummary/html/inherited.erb +9 -0
  169. data/templates/default/methodsummary/html/summary.erb +25 -0
  170. data/templates/default/methodsummary/text/header.erb +5 -0
  171. data/templates/default/methodsummary/text/included.erb +0 -0
  172. data/templates/default/methodsummary/text/inherited.erb +0 -0
  173. data/templates/default/methodsummary/text/summary.erb +3 -0
  174. data/templates/default/mixins/html/header.erb +4 -0
  175. data/templates/default/module/html/header.erb +4 -0
  176. data/templates/default/quickdoc/html/header.erb +15 -0
  177. data/templates/default/quickdoc/text/header.erb +12 -0
  178. data/templates/default/source/html/main.erb +15 -0
  179. data/templates/default/source/text/main.erb +4 -0
  180. data/templates/default/tags/html/header.erb +4 -0
  181. data/templates/default/tags/html/see.erb +13 -0
  182. data/templates/default/tags/html/tags.erb +20 -0
  183. data/templates/default/tags/text/header.erb +3 -0
  184. data/templates/default/tags/text/see.erb +5 -0
  185. data/templates/default/tags/text/tags.erb +7 -0
  186. data/templates/default/uml/dot/child.erb +1 -0
  187. data/templates/default/uml/dot/dependencies.erb +10 -0
  188. data/templates/default/uml/dot/header.erb +6 -0
  189. data/templates/default/uml/dot/info.erb +14 -0
  190. data/templates/default/uml/dot/subgraph.erb +6 -0
  191. data/templates/default/uml/dot/superclasses.erb +9 -0
  192. data/templates/default/uml/dot/unknown.erb +3 -0
  193. data/templates/default/uml/dot/unknown_child.erb +1 -0
  194. data/templates/default/visibilitygroup/html/header.erb +6 -0
  195. data/templates/javadoc/attributes/html/header.erb +16 -0
  196. data/templates/javadoc/class/html/header.erb +4 -0
  197. data/templates/javadoc/constants/html/constants.erb +9 -0
  198. data/templates/javadoc/constants/html/header.erb +3 -0
  199. data/templates/javadoc/constants/html/included.erb +12 -0
  200. data/templates/javadoc/constants/html/inherited.erb +12 -0
  201. data/templates/javadoc/constructor/html/header.erb +10 -0
  202. data/templates/javadoc/deprecated/html/main.erb +0 -0
  203. data/templates/javadoc/docstring/html/main.erb +6 -0
  204. data/templates/javadoc/fulldoc/html/all_methods.erb +25 -0
  205. data/templates/javadoc/fulldoc/html/all_namespaces.erb +19 -0
  206. data/templates/javadoc/fulldoc/html/app.js +18 -0
  207. data/templates/javadoc/fulldoc/html/header.erb +15 -0
  208. data/templates/javadoc/fulldoc/html/html_head.erb +3 -0
  209. data/templates/javadoc/fulldoc/html/index.erb +18 -0
  210. data/templates/javadoc/fulldoc/html/jquery.js +11 -0
  211. data/templates/javadoc/fulldoc/html/readme.erb +15 -0
  212. data/templates/javadoc/fulldoc/html/style.css +22 -0
  213. data/templates/javadoc/fulldoc/html/syntax_highlight.css +21 -0
  214. data/templates/javadoc/inheritance/html/header.erb +6 -0
  215. data/templates/javadoc/method/html/aliases.erb +6 -0
  216. data/templates/javadoc/method/html/header.erb +4 -0
  217. data/templates/javadoc/method/html/title.erb +4 -0
  218. data/templates/javadoc/methoddetails/html/header.erb +8 -0
  219. data/templates/javadoc/methoddetails/html/method_header.erb +0 -0
  220. data/templates/javadoc/methodmissing/html/header.erb +12 -0
  221. data/templates/javadoc/methodsignature/html/main.erb +8 -0
  222. data/templates/javadoc/methodsummary/html/header.erb +5 -0
  223. data/templates/javadoc/methodsummary/html/included.erb +12 -0
  224. data/templates/javadoc/methodsummary/html/inherited.erb +12 -0
  225. data/templates/javadoc/methodsummary/html/summary.erb +25 -0
  226. data/templates/javadoc/mixins/html/header.erb +5 -0
  227. data/templates/javadoc/module/html/header.erb +4 -0
  228. data/templates/javadoc/source/html/main.erb +15 -0
  229. data/templates/javadoc/tags/html/header.erb +5 -0
  230. data/templates/javadoc/tags/html/see.erb +8 -0
  231. data/templates/javadoc/tags/html/tags.erb +19 -0
  232. data/templates/javadoc/visibilitygroup/html/header.erb +5 -0
  233. metadata +352 -50
  234. data/README.pdf +0 -0
  235. data/lib/code_object.rb +0 -337
  236. data/lib/extra.rb +0 -8
  237. data/lib/formatter.rb +0 -90
  238. data/lib/handlers/all_handlers.rb +0 -2
  239. data/lib/handlers/attribute_handler.rb +0 -51
  240. data/lib/handlers/class_handler.rb +0 -30
  241. data/lib/handlers/class_variable_handler.rb +0 -9
  242. data/lib/handlers/code_object_handler.rb +0 -104
  243. data/lib/handlers/constant_handler.rb +0 -11
  244. data/lib/handlers/exception_handler.rb +0 -20
  245. data/lib/handlers/method_handler.rb +0 -28
  246. data/lib/handlers/mixin_handler.rb +0 -15
  247. data/lib/handlers/module_handler.rb +0 -9
  248. data/lib/handlers/visibility_handler.rb +0 -7
  249. data/lib/handlers/yield_handler.rb +0 -33
  250. data/lib/logger.rb +0 -19
  251. data/lib/namespace.rb +0 -98
  252. data/lib/quick_doc.rb +0 -104
  253. data/lib/ruby_lex.rb +0 -1321
  254. data/lib/source_parser.rb +0 -253
  255. data/lib/tag_library.rb +0 -175
  256. data/lib/tag_type.rb +0 -155
  257. data/templates/default/html/_fulldoc.erb +0 -64
  258. data/templates/default/html/class.erb +0 -226
  259. data/templates/default/html/method.erb +0 -20
  260. data/templates/default/html/module.erb +0 -126
  261. data/test/fixtures/docstring.txt +0 -23
  262. data/test/fixtures/docstring2.txt +0 -4
  263. data/test/test_code_object.rb +0 -66
  264. data/test/test_namespace.rb +0 -10
@@ -0,0 +1,16 @@
1
+ module YARD
2
+ module Serializers
3
+ class Base
4
+ attr_reader :options
5
+
6
+ def initialize(opts = {})
7
+ @options = SymbolHash.new(false).update(opts)
8
+ end
9
+
10
+ def before_serialize; end
11
+ def serialize(object, data) end
12
+ def after_serialize(data); end
13
+ def serialized_path(object) end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ require 'fileutils'
2
+
3
+ module YARD
4
+ module Serializers
5
+ class FileSystemSerializer < Base
6
+ attr_reader :basepath, :extension
7
+
8
+ def initialize(opts = {})
9
+ super
10
+ @basepath = (options[:basepath] || 'doc').to_s
11
+ @extension = (options.has_key?(:extension) ? options[:extension] : 'html').to_s
12
+ end
13
+
14
+ def serialize(object, data)
15
+ path = File.join(basepath, *serialized_path(object))
16
+ FileUtils.mkdir_p File.dirname(path)
17
+ log.debug "Serializing to #{path}"
18
+ File.open(path, "w") {|f| f.write data }
19
+ end
20
+
21
+ def serialized_path(object)
22
+ return object if object.is_a?(String)
23
+
24
+ objname = object.name.to_s
25
+ objname += '_' + object.scope.to_s[0,1] if object.is_a?(CodeObjects::MethodObject)
26
+ fspath = [objname + (extension.empty? ? '' : ".#{extension}")]
27
+ if object.namespace && object.namespace.path != ""
28
+ fspath.unshift *object.namespace.path.split(CodeObjects::NSEP)
29
+ end
30
+
31
+ # Don't change the filenames, it just makes it more complicated
32
+ # to figure out the original name.
33
+ #fspath.map! do |p|
34
+ # p.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
35
+ #end
36
+
37
+ # Remove special chars from filenames.
38
+ # Windows disallows \ / : * ? " < > | but we will just remove any
39
+ # non alphanumeric (plus period, underscore and dash).
40
+ fspath.map! do |p|
41
+ p.gsub(/[^\w\.-]/) {|x| '_' + x[0].to_s(16).upcase }
42
+ end
43
+
44
+ File.join(fspath)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,14 @@
1
+ module YARD
2
+ module Serializers
3
+ class ProcessSerializer < Base
4
+ def initialize(cmd)
5
+ @cmd = cmd
6
+ end
7
+
8
+ def serialize(object, data)
9
+ IO.popen(@cmd, 'w') {|io| io.write(data) }
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,21 @@
1
+ module YARD
2
+ module Serializers
3
+ class StdoutSerializer < Base
4
+ def initialize(wrap = nil)
5
+ @wrap = wrap
6
+ end
7
+
8
+ def serialize(object, data)
9
+ print(@wrap ? word_wrap(data, @wrap) : data)
10
+ end
11
+
12
+ private
13
+
14
+ def word_wrap(text, length = 80)
15
+ # See ruby-talk/10655 / Ernest Ellingson
16
+ text.gsub(/\t/," ").gsub(/.{1,50}(?:\s|\Z)/){($& +
17
+ 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n")}
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,98 @@
1
+ module YARD
2
+ module Tags
3
+ class DefaultFactory
4
+ ##
5
+ # Parses tag text and creates a new tag with descriptive text
6
+ #
7
+ # @param tag_name the name of the tag to parse
8
+ # @param [String] text the raw tag text
9
+ # @return [Tag] a tag object with the tag_name and text values filled
10
+ def parse_tag(tag_name, text)
11
+ Tag.new(tag_name, text)
12
+ end
13
+
14
+ ##
15
+ # Parses tag text and creates a new tag with a key name and descriptive text
16
+ #
17
+ # @param tag_name the name of the tag to parse
18
+ # @param [String] text the raw tag text
19
+ # @return [Tag] a tag object with the tag_name, name and text values filled
20
+ def parse_tag_with_name(tag_name, text)
21
+ name, text = *extract_name_from_text(text)
22
+ Tag.new(tag_name, text, nil, name)
23
+ end
24
+
25
+ ##
26
+ # Parses tag text and creates a new tag with formally declared types and
27
+ # descriptive text
28
+ #
29
+ # @param tag_name the name of the tag to parse
30
+ # @param [String] text the raw tag text
31
+ # @return [Tag] a tag object with the tag_name, types and text values filled
32
+ def parse_tag_with_types(tag_name, text)
33
+ types, text = *extract_types_from_text(text)
34
+ Tag.new(tag_name, text, types)
35
+ end
36
+
37
+ ##
38
+ # Parses tag text and creates a new tag with formally declared types, a key
39
+ # name and descriptive text
40
+ #
41
+ # @param tag_name the name of the tag to parse
42
+ # @param [String] text the raw tag text
43
+ # @return [Tag] a tag object with the tag_name, name, types and text values filled
44
+ def parse_tag_with_types_and_name(tag_name, text)
45
+ types, text = *extract_types_from_text(text)
46
+ name, text = *extract_name_from_text(text)
47
+ Tag.new(tag_name, text, types, name)
48
+ end
49
+
50
+ def parse_tag_with_raw_text(tag_name, text, raw_text)
51
+ Tag.new(tag_name, raw_text)
52
+ end
53
+
54
+ def parse_tag_with_raw_title_and_text(tag_name, text, raw_text)
55
+ title, desc = *extract_title_and_desc_from_raw_text(raw_text)
56
+ Tag.new(tag_name, desc, nil, title)
57
+ end
58
+
59
+ private
60
+
61
+ ##
62
+ # Extracts the name from raw tag text returning the name and remaining value
63
+ #
64
+ # @param [String] text the raw tag text
65
+ # @return [Array] an array holding the name as the first element and the
66
+ # value as the second element
67
+ def extract_name_from_text(text)
68
+ text.strip.split(" ", 2)
69
+ end
70
+
71
+ ##
72
+ # Extracts the type signatures from the raw tag text
73
+ #
74
+ # @param [String] text the raw tag text
75
+ # @return [Array] an array holding the value as the first element and
76
+ # the array of types as the second element
77
+ def extract_types_from_text(text)
78
+ types, text = [], text.strip
79
+ if text =~ /^\s*\[(.+?)\]\s*(.*)/
80
+ text, types = $2, $1.split(",").collect {|e| e.strip }
81
+ end
82
+ [types, text]
83
+ end
84
+
85
+ def extract_title_and_desc_from_raw_text(raw_text)
86
+ title, desc = nil, nil
87
+ if raw_text =~ /\A[ \t]\n/
88
+ desc = raw_text
89
+ else
90
+ raw_text = raw_text.split(/\r?\n/)
91
+ title = raw_text.shift.squeeze(' ').strip
92
+ desc = raw_text.join("\n")
93
+ end
94
+ [title, desc]
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,109 @@
1
+ module YARD
2
+ module Tags
3
+ ##
4
+ # Holds all the registered meta tags. If you want to extend YARD and add
5
+ # a new meta tag, you can do it in one of two ways.
6
+ #
7
+ # == Method #1
8
+ # Write your own +tagname_tag+ method that takes the raw text as a parameter.
9
+ # Example:
10
+ # def mytag_tag(text)
11
+ # Tag.parse_tag("mytag", text)
12
+ # end
13
+ #
14
+ # This will allow you to use @mytag TEXT to add meta data to classes through
15
+ # the docstring. {Tag} has a few convenience factory methods to create
16
+ #
17
+ # == Method #2
18
+ # Use {Library::define_tag!} to define a new tag by passing the tag name
19
+ # and the factory method to use when creating the tag. These definitions will
20
+ # be auto expanded into ruby code similar to what is shown in method #1. If you
21
+ # do not provide a factory method to use, it will default to {Tag::parse_tag}
22
+ # Example:
23
+ # define_tag :param, :with_types_and_name
24
+ # define_tag :author
25
+ #
26
+ # The first line will expand to the code:
27
+ # def param_tag(text) Tag.parse_tag_with_types_and_name(text) end
28
+ #
29
+ # The second line will expand to:
30
+ # def author_tag(text) Tag.parse_tag(text) end
31
+ #
32
+ # @see Library::define_tag
33
+ class Library
34
+ class << self
35
+ attr_reader :labels
36
+ attr_accessor :default_factory
37
+
38
+ def default_factory
39
+ @default_factory ||= DefaultFactory.new
40
+ end
41
+
42
+ def default_factory=(factory)
43
+ @default_factory = factory.is_a?(Class) ? factory.new : factory
44
+ end
45
+
46
+ ##
47
+ # Sorts the labels lexically by their label name, often used when displaying
48
+ # the tags.
49
+ #
50
+ # @return [Array<Symbol>, String] the sorted labels as an array of the tag name and label
51
+ def sorted_labels
52
+ labels.sort_by {|a| a.last.downcase }
53
+ end
54
+
55
+ ##
56
+ # Convenience method to define a new tag using one of {Tag}'s factory methods, or the
57
+ # regular {Tag::parse_tag} factory method if none is supplied.
58
+ #
59
+ # @param [#to_s] tag the tag name to create
60
+ # @param meth the {Tag} factory method to call when creating the tag
61
+ def define_tag(label, tag, meth = "")
62
+ class_eval <<-eof, __FILE__, __LINE__
63
+ def #{tag}_tag(text, raw_text)
64
+ send_to_factory(#{tag.inspect}, #{meth.inspect}, text, raw_text)
65
+ end
66
+ eof
67
+
68
+ @labels ||= SymbolHash.new(false)
69
+ @labels.update(tag => label)
70
+ tag
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def send_to_factory(tag_name, meth, text, raw_text)
77
+ meth = meth.to_s
78
+ send_name = "parse_tag" + (meth.empty? ? "" : "_" + meth)
79
+ if @factory.respond_to?(send_name)
80
+ arity = @factory.method(send_name).arity
81
+ @factory.send send_name, tag_name, text, *(arity == 3 ? [raw_text] : [])
82
+ else
83
+ raise NoMethodError, "Factory #{@factory.class_name} does not implement factory method :#{meth}."
84
+ end
85
+ end
86
+
87
+ public
88
+
89
+ def initialize(factory = Library.default_factory)
90
+ @factory = factory
91
+ end
92
+
93
+ define_tag "Parameters", :param, :with_types_and_name
94
+ define_tag "Yield Parameters", :yieldparam, :with_types_and_name
95
+ define_tag "Yields", :yield, :with_types
96
+ define_tag "Default Value", :default, :with_name
97
+ define_tag "Returns", :return, :with_types
98
+ define_tag "Deprecated", :deprecated
99
+ define_tag "Author", :author
100
+ define_tag "Raises", :raise, :with_types
101
+ define_tag "See Also", :see
102
+ define_tag "Since", :since
103
+ define_tag "Version", :version
104
+ define_tag "API Visibility", :api
105
+ define_tag "Todo Item", :todo
106
+ define_tag "Example", :example, :with_raw_title_and_text
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,47 @@
1
+ module YARD
2
+ module Tags
3
+ class MerbdocFactory < DefaultFactory
4
+ ##
5
+ # Parses tag text and creates a new tag with formally declared types and
6
+ # descriptive text
7
+ #
8
+ # @param tag_name the name of the tag to parse
9
+ # @param text<String> the raw tag text
10
+ # @return <Tag> a tag object with the tag_name, types and text values filled
11
+ def parse_tag_with_types(tag_name, text)
12
+ _, types, text = *extract_types_from_text(text)
13
+ # TODO warn if name value ('_') is not nil, because that's invalid syntax
14
+ Tag.new(tag_name, text, types)
15
+ end
16
+
17
+ ##
18
+ # Parses tag text and creates a new tag with formally declared types, a key
19
+ # name and descriptive text
20
+ #
21
+ # @param tag_name the name of the tag to parse
22
+ # @param text<String> the raw tag text
23
+ # @return <Tag> a tag object with the tag_name, name, types and text values filled
24
+ def parse_tag_with_types_and_name(tag_name, text)
25
+ name, types, text = *extract_types_from_text(text)
26
+ name, text = *extract_name_from_text(text) if name.nil?
27
+ Tag.new(tag_name, text, types, name)
28
+ end
29
+
30
+ private
31
+
32
+ ##
33
+ # Extracts the type signatures with an optional name from the raw tag text
34
+ #
35
+ # @param text<String> the raw tag text
36
+ # @return <Array> an array holding the name as the first element (nil if empty),
37
+ # array of types as the second element and the raw text as the last.
38
+ def extract_types_from_text(text)
39
+ name, types, text = nil, [], text.strip
40
+ if text =~ /^\s*(\S*)\s*<(.+?)>\s*(.*)/
41
+ name, text, types = $1, $3, $2.split(",").collect {|e| e.strip }
42
+ end
43
+ [name, types, text]
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,35 @@
1
+ module YARD
2
+ module Tags
3
+ class Tag
4
+ attr_reader :tag_name, :text, :types, :name
5
+
6
+ ##
7
+ # Creates a new tag object with a tag name and text. Optionally, formally declared types
8
+ # and a key name can be specified.
9
+ #
10
+ # Types are mainly for meta tags that rely on type information, such as +param+, +return+, etc.
11
+ #
12
+ # Key names are for tags that declare meta data for a specific key or name, such as +param+,
13
+ # +raise+, etc.
14
+ #
15
+ # @param tag_name the tag name to create the tag for
16
+ # @param [String] text the descriptive text for this tag
17
+ # @param [Array<String>] types optional type list of formally declared types
18
+ # for the tag
19
+ # @param [String] name optional key name which the tag refers to
20
+ def initialize(tag_name, text, types = nil, name = nil)
21
+ @tag_name, @text, @name, @types = tag_name.to_s, text, name, (types ? [types].flatten.compact : nil)
22
+ end
23
+
24
+ ##
25
+ # Convenience method to access the first type specified. This should mainly
26
+ # be used for tags that only specify one type.
27
+ #
28
+ # @return [String] the first of the list of specified types
29
+ # @see #types
30
+ def type
31
+ types.first
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,219 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe YARD::CodeObjects::Base do
4
+ before { Registry.clear }
5
+
6
+ it "should return a unique instance of any registered object" do
7
+ obj = ClassObject.new(:root, :Me)
8
+ obj2 = ModuleObject.new(:root, :Me)
9
+ obj.object_id.should == obj2.object_id
10
+
11
+ obj3 = ModuleObject.new(obj, :Too)
12
+ obj4 = CodeObjects::Base.new(obj3, :Hello)
13
+ obj4.parent = obj
14
+
15
+ obj5 = CodeObjects::Base.new(obj3, :hello)
16
+ obj4.object_id.should_not == obj5.object_id
17
+ end
18
+
19
+ it "should recall the block if #new is called on an existing object" do
20
+ o1 = ClassObject.new(:root, :Me) do |o|
21
+ o.docstring = "DOCSTRING"
22
+ end
23
+
24
+ o2 = ClassObject.new(:root, :Me) do |o|
25
+ o.docstring = "NOT_DOCSTRING"
26
+ end
27
+
28
+ o1.object_id.should == o2.object_id
29
+ o1.docstring.should == "NOT_DOCSTRING"
30
+ o2.docstring.should == "NOT_DOCSTRING"
31
+ end
32
+
33
+ it "should handle empty docstrings with #short_docstring" do
34
+ o1 = ClassObject.new(nil, :Me)
35
+ o1.short_docstring.should == ""
36
+ end
37
+
38
+ it "should return the first sentence with #short_docstring" do
39
+ o = ClassObject.new(nil, :Me)
40
+ o.docstring = "DOCSTRING. Another sentence"
41
+ o.short_docstring.should == "DOCSTRING."
42
+ end
43
+
44
+ it "should return the first paragraph with #short_docstring" do
45
+ o = ClassObject.new(nil, :Me)
46
+ o.docstring = "DOCSTRING, and other stuff\n\nAnother sentence."
47
+ o.short_docstring.should == "DOCSTRING, and other stuff."
48
+ end
49
+
50
+ it "should return proper short_docstring when docstring is changed" do
51
+ o = ClassObject.new(:root, :Me)
52
+ o.docstring = "DOCSTRING, and other stuff\n\nAnother sentence."
53
+ o.short_docstring.should == "DOCSTRING, and other stuff."
54
+ o.docstring = "DOCSTRING."
55
+ o.short_docstring.should == "DOCSTRING."
56
+ end
57
+
58
+ it "should not double the ending period in short_docstring" do
59
+ o = ClassObject.new(nil, :Me)
60
+ o.docstring = "Returns a list of tags specified by +name+ or all tags if +name+ is not specified.\n\nTest"
61
+ o.short_docstring.should == "Returns a list of tags specified by +name+ or all tags if +name+ is not specified."
62
+
63
+ Parser::SourceParser.parse_string <<-eof
64
+ ##
65
+ # Returns a list of tags specified by +name+ or all tags if +name+ is not specified.
66
+ #
67
+ # @param name the tag name to return data for, or nil for all tags
68
+ # @return [Array<Tags::Tag>] the list of tags by the specified tag name
69
+ def tags(name = nil)
70
+ return @tags if name.nil?
71
+ @tags.select {|tag| tag.tag_name.to_s == name.to_s }
72
+ end
73
+ eof
74
+ P('#tags').short_docstring.should == "Returns a list of tags specified by +name+ or all tags if +name+ is not specified."
75
+ end
76
+
77
+ it "should allow complex name and convert that to namespace" do
78
+ obj = CodeObjects::Base.new(nil, "A::B")
79
+ obj.namespace.path.should == "A"
80
+ obj.name.should == :B
81
+ end
82
+
83
+ it "should allow namespace to be nil and not register in the Registry" do
84
+ obj = CodeObjects::Base.new(nil, :Me)
85
+ obj.namespace.should == nil
86
+ Registry.at(:Me).should == nil
87
+ end
88
+
89
+ it "should allow namespace to be a NamespaceObject" do
90
+ ns = ModuleObject.new(:root, :Name)
91
+ obj = CodeObjects::Base.new(ns, :Me)
92
+ obj.namespace.should == ns
93
+ end
94
+
95
+ it "should allow :root to be the shorthand namespace of `Registry.root`" do
96
+ obj = CodeObjects::Base.new(:root, :Me)
97
+ obj.namespace.should == Registry.root
98
+ end
99
+
100
+
101
+ it "should not allow any other types as namespace" do
102
+ lambda { CodeObjects::Base.new("ROOT!", :Me) }.should raise_error(ArgumentError)
103
+ end
104
+
105
+ it "should register itself in the registry if namespace is supplied" do
106
+ obj = ModuleObject.new(:root, :Me)
107
+ Registry.at(:Me).should == obj
108
+
109
+ obj2 = ModuleObject.new(obj, :Too)
110
+ Registry.at(:"Me::Too").should == obj2
111
+ end
112
+
113
+ it "should set any attribute using #[]=" do
114
+ obj = ModuleObject.new(:root, :YARD)
115
+ obj[:some_attr] = "hello"
116
+ obj[:some_attr].should == "hello"
117
+ end
118
+
119
+ it "#[]= should use the accessor method if available" do
120
+ obj = CodeObjects::Base.new(:root, :YARD)
121
+ obj[:source] = "hello"
122
+ obj.source.should == "hello"
123
+ obj.source = "unhello"
124
+ obj[:source].should == "unhello"
125
+ end
126
+
127
+ it "should set attributes via attr= through method_missing" do
128
+ obj = CodeObjects::Base.new(:root, :YARD)
129
+ obj.something = 2
130
+ obj.something.should == 2
131
+ obj[:something].should == 2
132
+ end
133
+
134
+ it "should exist in the parent's #children after creation" do
135
+ obj = ModuleObject.new(:root, :YARD)
136
+ obj2 = MethodObject.new(obj, :testing)
137
+ obj.children.should include(obj2)
138
+ end
139
+
140
+ it "should parse comments into tags" do
141
+ obj = CodeObjects::Base.new(nil, :Object)
142
+ comments = <<-eof
143
+ @param name Hello world
144
+ how are you?
145
+ @param name2
146
+ this is a new line
147
+ @param name3 and this
148
+ is a new paragraph:
149
+
150
+ right here.
151
+ eof
152
+ obj.send(:parse_comments, comments)
153
+ obj.tags("param").each do |tag|
154
+ if tag.name == "name"
155
+ tag.text.should == "Hello world how are you?"
156
+ elsif tag.name == "name2"
157
+ tag.text.should == "this is a new line"
158
+ elsif tag.name == "name3"
159
+ tag.text.should == "and this is a new paragraph:\n\nright here."
160
+ end
161
+ end
162
+ end
163
+
164
+ it "should properly re-indent source starting from 0 indentation" do
165
+ obj = CodeObjects::Base.new(nil, :test)
166
+ obj.source = <<-eof
167
+ def mymethod
168
+ if x == 2 &&
169
+ 5 == 5
170
+ 3
171
+ else
172
+ 1
173
+ end
174
+ end
175
+ eof
176
+ obj.source.should == "def mymethod\n if x == 2 &&\n 5 == 5\n 3 \n else\n 1\n end\nend"
177
+
178
+ Registry.clear
179
+ Parser::SourceParser.parse_string <<-eof
180
+ def key?(key)
181
+ super(key)
182
+ end
183
+ eof
184
+ Registry.at('#key?').source.should == "def key?(key)\n super(key)\nend"
185
+
186
+ Registry.clear
187
+ Parser::SourceParser.parse_string <<-eof
188
+ def key?(key)
189
+ if x == 2
190
+ puts key
191
+ else
192
+ exit
193
+ end
194
+ end
195
+ eof
196
+ Registry.at('#key?').source.should == "def key?(key)\n if x == 2\n puts key\n else\n exit\n end\nend"
197
+ end
198
+
199
+ it "should not add newlines to source when parsing sub blocks" do
200
+ Parser::SourceParser.parse_string <<-eof
201
+ module XYZ
202
+ module ZYX
203
+ class ABC
204
+ def msg
205
+ hello_world
206
+ end
207
+ end
208
+ end
209
+ end
210
+ eof
211
+ Registry.at('XYZ::ZYX::ABC#msg').source.should == "def msg\n hello_world\nend"
212
+ end
213
+
214
+ it "should handle source for 'def x; end'" do
215
+ Registry.clear
216
+ Parser::SourceParser.parse_string "def x; 2 end"
217
+ Registry.at('#x').source.should == "def x; 2 end"
218
+ end
219
+ end