yard 0.2.2 → 0.2.3

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 (204) hide show
  1. data/LICENSE +1 -1
  2. data/README.markdown +200 -0
  3. data/Rakefile +6 -1
  4. data/benchmarks/format_args.rb +46 -0
  5. data/benchmarks/parsing.rb +13 -1
  6. data/benchmarks/rdoc_vs_yardoc.rb +10 -0
  7. data/benchmarks/ripper_parser.rb +12 -0
  8. data/docs/CODE_OBJECTS.markdown +121 -0
  9. data/docs/FAQ.markdown +34 -0
  10. data/docs/GENERATORS.markdown +211 -0
  11. data/docs/GETTING_STARTED.markdown +263 -0
  12. data/docs/GLOSSARY.markdown +13 -0
  13. data/docs/HANDLERS.markdown +158 -0
  14. data/docs/OVERVIEW.markdown +64 -0
  15. data/docs/PARSER.markdown +180 -0
  16. data/docs/TAGS.markdown +181 -0
  17. data/docs/WHATSNEW.markdown +96 -0
  18. data/docs/images/code-objects-class-diagram.png +0 -0
  19. data/docs/images/handlers-class-diagram.png +0 -0
  20. data/docs/images/overview-class-diagram.png +0 -0
  21. data/docs/images/parser-class-diagram.png +0 -0
  22. data/docs/images/tags-class-diagram.png +0 -0
  23. data/lib/yard.rb +4 -1
  24. data/lib/yard/autoload.rb +79 -31
  25. data/lib/yard/cli/yard_graph.rb +8 -2
  26. data/lib/yard/cli/yardoc.rb +61 -8
  27. data/lib/yard/code_objects/base.rb +78 -135
  28. data/lib/yard/code_objects/class_object.rb +9 -8
  29. data/lib/yard/code_objects/constant_object.rb +1 -0
  30. data/lib/yard/code_objects/extended_method_object.rb +9 -0
  31. data/lib/yard/code_objects/method_object.rb +18 -5
  32. data/lib/yard/code_objects/module_object.rb +8 -1
  33. data/lib/yard/code_objects/namespace_object.rb +25 -16
  34. data/lib/yard/code_objects/proxy.rb +22 -22
  35. data/lib/yard/core_ext/file.rb +1 -1
  36. data/lib/yard/core_ext/string.rb +0 -4
  37. data/lib/yard/core_ext/symbol_hash.rb +3 -2
  38. data/lib/yard/docstring.rb +180 -0
  39. data/lib/yard/generators/base.rb +33 -13
  40. data/lib/yard/generators/class_generator.rb +4 -2
  41. data/lib/yard/generators/constants_generator.rb +3 -2
  42. data/lib/yard/generators/full_doc_generator.rb +76 -9
  43. data/lib/yard/generators/helpers/base_helper.rb +18 -1
  44. data/lib/yard/generators/helpers/filter_helper.rb +2 -2
  45. data/lib/yard/generators/helpers/html_helper.rb +94 -39
  46. data/lib/yard/generators/helpers/html_syntax_highlight_helper.rb +49 -0
  47. data/lib/yard/generators/helpers/markup_helper.rb +86 -0
  48. data/lib/yard/generators/helpers/method_helper.rb +23 -7
  49. data/lib/yard/generators/method_generator.rb +15 -3
  50. data/lib/yard/generators/method_listing_generator.rb +3 -3
  51. data/lib/yard/generators/mixins_generator.rb +8 -2
  52. data/lib/yard/generators/module_generator.rb +3 -2
  53. data/lib/yard/generators/overloads_generator.rb +20 -0
  54. data/lib/yard/generators/quick_doc_generator.rb +3 -9
  55. data/lib/yard/generators/root_generator.rb +32 -0
  56. data/lib/yard/generators/source_generator.rb +2 -17
  57. data/lib/yard/generators/tags_generator.rb +34 -6
  58. data/lib/yard/generators/uml_generator.rb +16 -6
  59. data/lib/yard/handlers/base.rb +88 -253
  60. data/lib/yard/handlers/processor.rb +72 -0
  61. data/lib/yard/handlers/ruby/alias_handler.rb +38 -0
  62. data/lib/yard/handlers/ruby/attribute_handler.rb +69 -0
  63. data/lib/yard/handlers/ruby/base.rb +72 -0
  64. data/lib/yard/handlers/ruby/class_condition_handler.rb +70 -0
  65. data/lib/yard/handlers/ruby/class_handler.rb +74 -0
  66. data/lib/yard/handlers/ruby/class_variable_handler.rb +11 -0
  67. data/lib/yard/handlers/ruby/constant_handler.rb +12 -0
  68. data/lib/yard/handlers/ruby/exception_handler.rb +22 -0
  69. data/lib/yard/handlers/ruby/extend_handler.rb +19 -0
  70. data/lib/yard/handlers/{alias_handler.rb → ruby/legacy/alias_handler.rb} +3 -4
  71. data/lib/yard/handlers/{attribute_handler.rb → ruby/legacy/attribute_handler.rb} +2 -2
  72. data/lib/yard/handlers/ruby/legacy/base.rb +198 -0
  73. data/lib/yard/handlers/{class_handler.rb → ruby/legacy/class_handler.rb} +18 -6
  74. data/lib/yard/handlers/{class_variable_handler.rb → ruby/legacy/class_variable_handler.rb} +1 -1
  75. data/lib/yard/handlers/{constant_handler.rb → ruby/legacy/constant_handler.rb} +2 -2
  76. data/lib/yard/handlers/{exception_handler.rb → ruby/legacy/exception_handler.rb} +3 -3
  77. data/lib/yard/handlers/ruby/legacy/extend_handler.rb +18 -0
  78. data/lib/yard/handlers/ruby/legacy/method_handler.rb +31 -0
  79. data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +28 -0
  80. data/lib/yard/handlers/{module_handler.rb → ruby/legacy/module_handler.rb} +1 -1
  81. data/lib/yard/handlers/{visibility_handler.rb → ruby/legacy/visibility_handler.rb} +1 -1
  82. data/lib/yard/handlers/{yield_handler.rb → ruby/legacy/yield_handler.rb} +4 -4
  83. data/lib/yard/handlers/ruby/method_condition_handler.rb +7 -0
  84. data/lib/yard/handlers/ruby/method_handler.rb +48 -0
  85. data/lib/yard/handlers/ruby/mixin_handler.rb +25 -0
  86. data/lib/yard/handlers/ruby/module_handler.rb +9 -0
  87. data/lib/yard/handlers/ruby/visibility_handler.rb +18 -0
  88. data/lib/yard/handlers/ruby/yield_handler.rb +28 -0
  89. data/lib/yard/parser/ruby/ast_node.rb +263 -0
  90. data/lib/yard/parser/{ruby_lex.rb → ruby/legacy/ruby_lex.rb} +258 -259
  91. data/lib/yard/parser/{statement.rb → ruby/legacy/statement.rb} +8 -4
  92. data/lib/yard/parser/ruby/legacy/statement_list.rb +262 -0
  93. data/lib/yard/parser/{token_list.rb → ruby/legacy/token_list.rb} +1 -1
  94. data/lib/yard/parser/ruby/ruby_parser.rb +307 -0
  95. data/lib/yard/parser/source_parser.rb +76 -45
  96. data/lib/yard/rake/yardoc_task.rb +6 -1
  97. data/lib/yard/registry.rb +45 -19
  98. data/lib/yard/serializers/file_system_serializer.rb +8 -3
  99. data/lib/yard/tags/default_factory.rb +70 -10
  100. data/lib/yard/tags/default_tag.rb +12 -0
  101. data/lib/yard/tags/library.rb +65 -26
  102. data/lib/yard/tags/option_tag.rb +12 -0
  103. data/lib/yard/tags/overload_tag.rb +62 -0
  104. data/lib/yard/tags/ref_tag.rb +7 -0
  105. data/lib/yard/tags/ref_tag_list.rb +27 -0
  106. data/lib/yard/tags/tag.rb +1 -0
  107. data/lib/yard/tags/tag_format_error.rb +6 -0
  108. data/spec/cli/yardoc_spec.rb +43 -0
  109. data/spec/code_objects/base_spec.rb +56 -68
  110. data/spec/code_objects/class_object_spec.rb +18 -6
  111. data/spec/code_objects/constants_spec.rb +2 -0
  112. data/spec/code_objects/method_object_spec.rb +33 -5
  113. data/spec/code_objects/module_object_spec.rb +66 -8
  114. data/spec/code_objects/namespace_object_spec.rb +37 -17
  115. data/spec/code_objects/proxy_spec.rb +13 -2
  116. data/spec/core_ext/string_spec.rb +14 -2
  117. data/spec/core_ext/symbol_hash_spec.rb +9 -3
  118. data/spec/docstring_spec.rb +139 -0
  119. data/spec/generators/full_doc_generator_spec.rb +29 -0
  120. data/spec/generators/helpers/html_helper_spec.rb +74 -0
  121. data/spec/generators/helpers/markup_helper_spec.rb +95 -0
  122. data/spec/handlers/alias_handler_spec.rb +16 -3
  123. data/spec/handlers/attribute_handler_spec.rb +1 -1
  124. data/spec/handlers/base_spec.rb +15 -141
  125. data/spec/handlers/class_condition_handler_spec.rb +49 -0
  126. data/spec/handlers/class_handler_spec.rb +44 -3
  127. data/spec/handlers/class_variable_handler_spec.rb +1 -1
  128. data/spec/handlers/constant_handler_spec.rb +1 -1
  129. data/spec/handlers/examples/alias_handler_001.rb.txt +7 -3
  130. data/spec/handlers/examples/class_condition_handler_001.rb.txt +61 -0
  131. data/spec/handlers/examples/class_handler_001.rb.txt +33 -0
  132. data/spec/handlers/examples/exception_handler_001.rb.txt +1 -1
  133. data/spec/handlers/examples/extend_handler_001.rb.txt +8 -0
  134. data/spec/handlers/examples/method_condition_handler_001.rb.txt +10 -0
  135. data/spec/handlers/examples/method_handler_001.rb.txt +16 -4
  136. data/spec/handlers/examples/mixin_handler_001.rb.txt +10 -2
  137. data/spec/handlers/examples/module_handler_001.rb.txt +4 -0
  138. data/spec/handlers/examples/visibility_handler_001.rb.txt +1 -1
  139. data/spec/handlers/exception_handler_spec.rb +2 -2
  140. data/spec/handlers/extend_handler_spec.rb +15 -0
  141. data/spec/handlers/legacy_base_spec.rb +128 -0
  142. data/spec/handlers/method_condition_handler_spec.rb +14 -0
  143. data/spec/handlers/method_handler_spec.rb +38 -5
  144. data/spec/handlers/mixin_handler_spec.rb +15 -7
  145. data/spec/handlers/module_handler_spec.rb +5 -1
  146. data/spec/handlers/processor_spec.rb +19 -0
  147. data/spec/handlers/ruby/base_spec.rb +90 -0
  148. data/spec/handlers/ruby/legacy/base_spec.rb +53 -0
  149. data/spec/handlers/spec_helper.rb +22 -16
  150. data/spec/handlers/visibility_handler_spec.rb +4 -4
  151. data/spec/handlers/yield_handler_spec.rb +1 -1
  152. data/spec/parser/ruby/ast_node_spec.rb +15 -0
  153. data/spec/parser/ruby/legacy/statement_list_spec.rb +145 -0
  154. data/spec/parser/{token_list_spec.rb → ruby/legacy/token_list_spec.rb} +4 -4
  155. data/spec/parser/source_parser_spec.rb +0 -15
  156. data/spec/rake/yardoc_task_spec.rb +48 -0
  157. data/spec/registry_spec.rb +28 -2
  158. data/spec/serializers/file_system_serializer_spec.rb +7 -1
  159. data/spec/spec_helper.rb +1 -1
  160. data/spec/tags/default_factory_spec.rb +135 -0
  161. data/spec/tags/default_tag_spec.rb +11 -0
  162. data/spec/tags/overload_tag_spec.rb +35 -0
  163. data/spec/tags/ref_tag_list_spec.rb +53 -0
  164. data/templates/default/attributes/html/header.erb +17 -5
  165. data/templates/default/attributes/text/header.erb +1 -1
  166. data/templates/default/fulldoc/html/all_files.erb +19 -0
  167. data/templates/default/fulldoc/html/all_methods.erb +8 -7
  168. data/templates/default/fulldoc/html/all_namespaces.erb +4 -1
  169. data/templates/default/fulldoc/html/app.js +1 -1
  170. data/templates/default/fulldoc/html/{readme.erb → file.erb} +2 -2
  171. data/templates/default/fulldoc/html/header.erb +1 -1
  172. data/templates/default/fulldoc/html/index.erb +4 -3
  173. data/templates/default/fulldoc/html/style.css +13 -3
  174. data/templates/default/fulldoc/html/syntax_highlight.css +8 -5
  175. data/templates/default/method/text/header.erb +1 -0
  176. data/templates/default/method/text/title.erb +1 -0
  177. data/templates/default/methodsignature/html/main.erb +10 -8
  178. data/templates/default/methodsignature/text/main.erb +4 -1
  179. data/templates/default/methodsummary/html/summary.erb +8 -4
  180. data/templates/default/methodsummary/text/summary.erb +4 -1
  181. data/templates/default/mixins/html/header.erb +3 -3
  182. data/templates/default/overloads/html/header.erb +8 -0
  183. data/templates/default/overloads/text/header.erb +8 -0
  184. data/templates/default/root/html/header.erb +4 -0
  185. data/templates/default/tags/html/example.erb +20 -0
  186. data/templates/default/tags/html/option.erb +27 -0
  187. data/templates/default/tags/html/param.erb +21 -0
  188. data/templates/default/tags/html/tags.erb +4 -1
  189. data/templates/default/tags/html/todo.erb +8 -0
  190. data/templates/default/tags/text/example.erb +14 -0
  191. data/templates/default/tags/text/header.erb +3 -3
  192. data/templates/default/tags/text/option.erb +5 -0
  193. data/templates/default/tags/text/param.erb +9 -0
  194. data/templates/default/uml/dot/dependencies.erb +1 -1
  195. data/templates/default/uml/dot/info.erb +1 -1
  196. data/templates/default/uml/dot/superclasses.erb +2 -2
  197. data/templates/javadoc/methodsummary/html/summary.erb +2 -2
  198. data/templates/javadoc/mixins/html/header.erb +3 -3
  199. metadata +108 -139
  200. data/README +0 -211
  201. data/lib/yard/handlers/method_handler.rb +0 -27
  202. data/lib/yard/handlers/mixin_handler.rb +0 -16
  203. data/lib/yard/parser/statement_list.rb +0 -167
  204. data/lib/yard/tags/merbdoc_factory.rb +0 -47
@@ -12,18 +12,18 @@ module YARD
12
12
  def initialize(namespace, name)
13
13
  namespace = Registry.root if !namespace || namespace == :root
14
14
 
15
- if name =~ /^#{NSEP}/
15
+ if name =~ /^#{NSEPQ}/
16
16
  namespace = Registry.root
17
17
  name = name[2..-1]
18
18
  end
19
19
 
20
- if name =~ /(?:#{NSEP}|#{ISEP})([^#{NSEP}#{ISEP}]+)$/
20
+ if name =~ /(?:#{NSEPQ}|#{ISEPQ}|#{CSEPQ})([^#{NSEPQ}#{ISEPQ}#{CSEPQ}]+)$/
21
21
  @orignamespace, @origname = namespace, name
22
22
  @imethod = true if name.include? ISEP
23
- namespace = $`.empty? ? Registry.root : Proxy.new(namespace, $`)
23
+ namespace = Proxy.new(namespace, $`) unless $`.empty?
24
24
  name = $1
25
25
  end
26
-
26
+
27
27
  @name = name.to_sym
28
28
  @namespace = namespace
29
29
 
@@ -34,8 +34,8 @@ module YARD
34
34
  # If the name begins with "::" (like "::String")
35
35
  # this is definitely a root level object, so
36
36
  # remove the namespace and attach it to the root
37
- if @name =~ /^#{NSEP}/
38
- @name.gsub!(/^#{NSEP}/, '')
37
+ if @name =~ /^#{NSEPQ}/
38
+ @name.gsub!(/^#{NSEPQ}/, '')
39
39
  @namespace = Registry.root
40
40
  end
41
41
  end
@@ -54,8 +54,16 @@ module YARD
54
54
  else
55
55
  if @namespace == Registry.root
56
56
  (@imethod ? ISEP : "") + name.to_s
57
- else
58
- @origname || name.to_s
57
+ elsif @origname
58
+ if @origname =~ /^[A-Z]/
59
+ @origname
60
+ else
61
+ [namespace.path, @origname].join
62
+ end
63
+ elsif name.to_s =~ /^[A-Z]/ # const
64
+ name.to_s
65
+ else # class meth?
66
+ [namespace.path, name.to_s].join(CSEP)
59
67
  end
60
68
  end
61
69
  end
@@ -117,18 +125,10 @@ module YARD
117
125
  def kind_of?(klass)
118
126
  self.class <= klass
119
127
  end
120
-
121
- def object_id
122
- if obj = to_obj
123
- obj.object_id
124
- else
125
- nil
126
- end
127
- end
128
128
 
129
- def respond_to?(meth)
129
+ def respond_to?(meth, include_private = false)
130
130
  if obj = to_obj
131
- obj.respond_to?(meth)
131
+ obj.respond_to?(meth, include_private)
132
132
  else
133
133
  super
134
134
  end
@@ -166,7 +166,7 @@ module YARD
166
166
  #
167
167
  # @return [Base, nil] the registered code object or nil
168
168
  def to_obj
169
- @obj ||= Registry.resolve(@namespace, @name)
169
+ @obj ||= Registry.resolve(@namespace, (@imethod ? ISEP : '') + @name.to_s)
170
170
  end
171
171
  end
172
172
  end
@@ -176,8 +176,8 @@ end
176
176
  # via a path
177
177
  #
178
178
  # @see YARD::CodeObjects::Proxy
179
- # @see YARD::Registry::resolve
179
+ # @see YARD::Registry#resolve
180
180
  def P(namespace, name = nil)
181
181
  namespace, name = nil, namespace if name.nil?
182
- YARD::Registry.resolve(namespace, name, true)
183
- end
182
+ YARD::Registry.resolve(namespace, name, false, true)
183
+ end
@@ -4,7 +4,7 @@ class File
4
4
  # Turns a path +to+ into a relative path from starting
5
5
  # point +from+. The argument +from+ is assumed to be
6
6
  # a filename. To treat it as a directory, make sure it
7
- # ends in {File::SEPARATOR} ('/' on UNIX filesystems).
7
+ # ends in `File::SEPARATOR` ('/' on UNIX filesystems).
8
8
  #
9
9
  # @param [String] from the starting filename
10
10
  # (or directory with +from_isdir+ set to +true+).
@@ -1,12 +1,8 @@
1
1
  class String
2
- # @it should turn hello_world into HelloWorld
3
- # "hello_world".camelcase.should == "HelloWorld"
4
2
  def underscore
5
3
  gsub(/([a-z])([A-Z])/, '\1_\2').downcase
6
4
  end
7
5
 
8
- # @it should turn HelloWorld into hello_world
9
- # "HelloWorld".underscore.should == "hello_world"
10
6
  def camelcase
11
7
  gsub(/([a-z])_([a-z])/i) { $1 + $2.upcase }.sub(/^(.)/) { $1.upcase }
12
8
  end
@@ -20,5 +20,6 @@ class SymbolHash < Hash
20
20
  def delete(key) super(key.to_sym) end
21
21
  def has_key?(key) super(key.to_sym) end
22
22
  def update(hsh) hsh.each {|k,v| self[k] = v }; self end
23
- alias_method :merge, :update
24
- end
23
+ alias_method :merge!, :update
24
+ def merge(hsh) dup.merge!(hsh) end
25
+ end
@@ -0,0 +1,180 @@
1
+ module YARD
2
+ class Docstring < String
3
+ attr_reader :ref_tags
4
+ attr_accessor :object
5
+
6
+ def initialize(content = '', object = nil)
7
+ @tag_factory = Tags::Library.new
8
+ @tags, @ref_tags = [], []
9
+ @object = object
10
+
11
+ replace parse_comments(content)
12
+ end
13
+
14
+ ##
15
+ # Gets the first line of a docstring to the period or the first paragraph.
16
+ #
17
+ # @return [String] The first line or paragraph of the docstring; always ends with a period.
18
+ def summary
19
+ @summmary ||= (split(/\.|\r?\n\r?\n/).first || '')
20
+ @summmary += '.' unless @summmary.empty?
21
+ @summmary
22
+ end
23
+
24
+ ##
25
+ # Adds a tag or reftag object to the tag list
26
+ #
27
+ # @param [Tags::Tag, Tags::RefTag] *tags list of tag objects to add
28
+ def add_tag(*tags)
29
+ tags.each_with_index do |tag, i|
30
+ case tag
31
+ when Tags::Tag
32
+ tag.object = object
33
+ @tags << tag
34
+ when Tags::RefTag
35
+ @ref_tags << tag
36
+ else
37
+ raise ArgumentError, "expected Tag or RefTag, got #{tag.class} (at index #{i})"
38
+ end
39
+ end
40
+ end
41
+
42
+ ##
43
+ # Convenience method to return the first tag
44
+ # object in the list of tag objects of that name
45
+ #
46
+ # @example
47
+ # doc = YARD::Docstring.new("@return zero when nil")
48
+ # doc.tag(:return).text # => "zero when nil"
49
+ #
50
+ # @param [#to_s] name the tag name to return data for
51
+ # @return [Tags::Tag] the first tag in the list of {#tags}
52
+ def tag(name)
53
+ tags.find {|tag| tag.tag_name.to_s == name.to_s }
54
+ end
55
+
56
+ ##
57
+ # Returns a list of tags specified by +name+ or all tags if +name+ is not specified.
58
+ #
59
+ # @param name the tag name to return data for, or nil for all tags
60
+ # @return [Array<Tags::Tag>] the list of tags by the specified tag name
61
+ def tags(name = nil)
62
+ list = @tags + convert_ref_tags
63
+ return list unless name
64
+ list.select {|tag| tag.tag_name.to_s == name.to_s }
65
+ end
66
+
67
+ ##
68
+ # Returns true if at least one tag by the name +name+ was declared
69
+ #
70
+ # @param [String] name the tag name to search for
71
+ # @return [Boolean] whether or not the tag +name+ was declared
72
+ def has_tag?(name)
73
+ tags.any? {|tag| tag.tag_name.to_s == name.to_s }
74
+ end
75
+
76
+ ##
77
+ # Returns true if the docstring has no content
78
+ #
79
+ # @return [Boolean] whether or not the docstring has content
80
+ def blank?
81
+ empty? && @tags.empty? && @ref_tags.empty?
82
+ end
83
+
84
+ private
85
+
86
+ def convert_ref_tags
87
+ list = @ref_tags.reject {|t| CodeObjects::Proxy === t.owner }
88
+ list.map {|t| t.tags }.flatten
89
+ end
90
+
91
+ ##
92
+ # Creates a {RefTag}
93
+ def create_ref_tag(tag_name, name, object)
94
+ @ref_tags << Tags::RefTagList.new(tag_name, object, name)
95
+ end
96
+
97
+ ##
98
+ # Creates a tag from the TagFactory
99
+ #
100
+ def create_tag(tag_name, tag_buf, raw_buf)
101
+ if tag_buf =~ /\A\s*(?:(\S+)\s+)?\(\s*see\s+(\S+)\s*\)\s*\Z/
102
+ return create_ref_tag(tag_name, $1, $2)
103
+ end
104
+
105
+ tag_method = "#{tag_name}_tag"
106
+ if tag_name && @tag_factory.respond_to?(tag_method)
107
+ if @tag_factory.method(tag_method).arity == 2
108
+ add_tag *@tag_factory.send(tag_method, tag_buf, raw_buf.join("\n"))
109
+ else
110
+ add_tag *@tag_factory.send(tag_method, tag_buf)
111
+ end
112
+ else
113
+ log.warn "Unknown tag @#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "")
114
+ end
115
+ rescue Tags::TagFormatError
116
+ log.warn "Invalid tag format for @#{tag_name}" + (object ? " in file `#{object.file}` near line #{object.line}" : "")
117
+ end
118
+
119
+ ##
120
+ # Parses out comments split by newlines into a new code object
121
+ #
122
+ # @param [String] comments
123
+ # the newline delimited array of comments. If the comments
124
+ # are passed as a String, they will be split by newlines.
125
+ #
126
+ # @return [String] the non-metadata portion of the comments to
127
+ # be used as a docstring
128
+ def parse_comments(comments)
129
+ return '' if !comments || comments.empty?
130
+ meta_match = /^@(\S+)\s*(.*)/
131
+ comments = comments.split(/\r?\n/) if comments.is_a? String
132
+ docstring = ""
133
+
134
+ indent, last_indent = comments.first[/^\s*/].length, 0
135
+ orig_indent = 0
136
+ last_line = ""
137
+ tag_name, tag_klass, tag_buf, raw_buf = nil, nil, "", []
138
+
139
+ (comments+['']).each_with_index do |line, index|
140
+ indent = line[/^\s*/].length
141
+ empty = (line =~ /^\s*$/ ? true : false)
142
+ done = comments.size == index
143
+
144
+ if tag_name && (((indent < orig_indent && !empty) || done) ||
145
+ (indent <= last_indent && line =~ meta_match))
146
+ create_tag(tag_name, tag_buf, raw_buf)
147
+ tag_name, tag_buf, raw_buf = nil, '', []
148
+ orig_indent = 0
149
+ end
150
+
151
+ # Found a meta tag
152
+ if line =~ meta_match
153
+ orig_indent = indent
154
+ tag_name, tag_buf = $1, $2
155
+ raw_buf = [tag_buf.dup]
156
+ elsif tag_name && indent >= orig_indent && !empty
157
+ # Extra data added to the tag on the next line
158
+ last_empty = last_line =~ /^[ \t]*$/ ? true : false
159
+
160
+ if last_empty
161
+ tag_buf << "\n\n"
162
+ raw_buf << ''
163
+ end
164
+
165
+ tag_buf << line.gsub(/^[ \t]{#{indent}}/, last_empty ? '' : ' ')
166
+ raw_buf << line.gsub(/^[ \t]{#{orig_indent}}/, '')
167
+ elsif !tag_name
168
+ # Regular docstring text
169
+ docstring << line << "\n"
170
+ end
171
+
172
+ last_indent = indent
173
+ last_line = line
174
+ end
175
+
176
+ # Remove trailing/leading whitespace / newlines
177
+ docstring.gsub!(/\A[\r\n\s]+|[\r\n\s]+\Z/, '')
178
+ end
179
+ end
180
+ end
@@ -23,7 +23,23 @@ module YARD
23
23
  def register_template_path(path)
24
24
  template_paths.unshift(path)
25
25
  end
26
-
26
+
27
+ # Calls the +Proc+ object or method name before generating all or a specific
28
+ # section. The callback should return +false+ if the section is to be
29
+ # skipped.
30
+ #
31
+ # @overload before_section(method_name)
32
+ # @param [Symbol] method_name the name of the method to call before
33
+ # running the generator.
34
+ #
35
+ # @overload before_section(proc)
36
+ # @param [Proc] proc should return +false+ if section should be skipped.
37
+ #
38
+ # @overload before_section(section, condition)
39
+ # Only calls the +Proc+ or method if it matches the passed +section+
40
+ #
41
+ # @param [Object] section one of the section items in {#sections_for}
42
+ # @param [Symbol, Proc] condition see the first two overloads
27
43
  def before_section(*args)
28
44
  if args.size == 1
29
45
  before_section_filters.push [nil, args.first]
@@ -64,9 +80,7 @@ module YARD
64
80
  # @param [Class] generator
65
81
  # the generator class to use.
66
82
  #
67
- # @options opts
68
- # :ignore_serializer -> true => value
69
- #
83
+ # @option opts :ignore_serializer [Boolean] (true) whether or not the serializer is ignored.
70
84
  #
71
85
  def G(generator, opts = {})
72
86
  opts = SymbolHash[:ignore_serializer => true].update(opts)
@@ -82,6 +96,7 @@ module YARD
82
96
  opts = SymbolHash[
83
97
  :format => :html,
84
98
  :template => :default,
99
+ :markup => :rdoc,
85
100
  :serializer => nil,
86
101
  :verifier => nil
87
102
  ].update(opts).update(extra_opts)
@@ -110,7 +125,7 @@ module YARD
110
125
  serializer.before_serialize if serializer && !ignore_serializer
111
126
 
112
127
  list.each do |object|
113
- next unless object && object.is_a?(CodeObjects::Base)
128
+ next unless object && !object.is_a?(CodeObjects::Proxy)
114
129
 
115
130
  objout = ""
116
131
  @current_object = object
@@ -247,24 +262,29 @@ module YARD
247
262
  object, file, locals = current_object, object, (file||{})
248
263
  end
249
264
 
250
- __path = template_path(file.to_s + '.erb', generator_name)
251
- __f = find_template(__path)
252
- if __f
253
- __l = locals.map {|k,v| "#{k} = #{v.inspect}" unless k.to_s == "__f" }.join(";")
265
+ path = template_path(file.to_s + '.erb', generator_name)
266
+ filename = find_template(path)
267
+ if filename
254
268
  begin
255
- erb("<% #{__l} %>" + File.read(__f)).result(binding)
269
+ render_method(object, filename, locals, &block)
256
270
  rescue => e
257
271
  log.error "#{e.class.class_name}: #{e.message}"
258
- log.error "in generator #{self.class} section #{file} on '#{object}'"
272
+ log.error "in generator #{self.class}: #{filename}"
259
273
  log.error e.backtrace[0..10].join("\n")
260
274
  exit
261
275
  end
262
276
  else
263
- log.warn "Cannot find template `#{__path}`"
277
+ log.warn "Cannot find template `#{path}`"
264
278
  ""
265
279
  end
266
280
  end
267
281
 
282
+ def render_method(object, filename, locals = {}, &block)
283
+ l = locals.map {|k,v| "#{k} = locals[#{k.inspect}]" }.join(";")
284
+ src = erb("<% #{l} %>" + File.read(filename)).src
285
+ instance_eval(src, filename, 1)
286
+ end
287
+
268
288
  def erb(str)
269
289
  ERB.new(str, nil, '<>')
270
290
  end
@@ -282,4 +302,4 @@ module YARD
282
302
  end
283
303
  end
284
304
  end
285
- end
305
+ end
@@ -8,8 +8,10 @@ module YARD
8
8
  :header,
9
9
  [
10
10
  G(InheritanceGenerator),
11
- G(MixinsGenerator),
11
+ G(MixinsGenerator, :scope => :class),
12
+ G(MixinsGenerator, :scope => :instance),
12
13
  G(DocstringGenerator),
14
+ G(TagsGenerator),
13
15
  G(AttributesGenerator),
14
16
  G(ConstantsGenerator),
15
17
  G(ConstructorGenerator),
@@ -22,4 +24,4 @@ module YARD
22
24
  end
23
25
  end
24
26
  end
25
- end
27
+ end
@@ -1,6 +1,7 @@
1
1
  module YARD
2
2
  module Generators
3
3
  class ConstantsGenerator < Base
4
+ before_generate :is_namespace?
4
5
  before_section :constants, :has_constants?
5
6
  before_section :inherited, :has_inherited_constants?
6
7
  before_section :included, :has_included_constants?
@@ -60,7 +61,7 @@ module YARD
60
61
  #
61
62
  def included_constants_by_module
62
63
  all_consts = current_object.included_constants
63
- current_object.mixins.each do |superclass|
64
+ current_object.instance_mixins.each do |superclass|
64
65
  next if superclass.is_a?(CodeObjects::Proxy)
65
66
  opts = { :included => false, :inherited => false }
66
67
  consts = superclass.constants(opts).select {|c| all_consts.include?(c) }
@@ -70,4 +71,4 @@ module YARD
70
71
  end
71
72
  end
72
73
  end
73
- end
74
+ end
@@ -2,12 +2,15 @@ module YARD
2
2
  module Generators
3
3
  class FullDocGenerator < Base
4
4
  before_generate :is_namespace?
5
+ before_list :setup_options
5
6
  before_list :generate_assets
6
7
  before_list :generate_index
7
- before_list :generate_readme
8
+ before_list :generate_files
8
9
 
9
10
  def sections_for(object)
10
11
  case object
12
+ when CodeObjects::RootObject
13
+ [:header, [G(RootGenerator)]]
11
14
  when CodeObjects::ClassObject
12
15
  [:header, [G(ClassGenerator)]]
13
16
  when CodeObjects::ModuleObject
@@ -16,6 +19,11 @@ module YARD
16
19
  end
17
20
 
18
21
  protected
22
+
23
+ def setup_options
24
+ options[:readme] ||= Dir['{README,README.*}']
25
+ options[:files] ||= []
26
+ end
19
27
 
20
28
  def css_file; 'style.css' end
21
29
  def css_syntax_file; 'syntax_highlight.css' end
@@ -28,6 +36,12 @@ module YARD
28
36
  end.to_s
29
37
  end
30
38
 
39
+ def readme_file_exists?; not readme_file.empty?; end
40
+
41
+ def extra_files
42
+ [readme_file] + options[:files]
43
+ end
44
+
31
45
  def generate_assets
32
46
  if format == :html && serializer
33
47
  [css_file, css_syntax_file, js_file, js_app_file].each do |filename|
@@ -38,22 +52,75 @@ module YARD
38
52
  true
39
53
  end
40
54
 
41
- def generate_index
55
+ def generate_index(all_objects)
42
56
  if format == :html && serializer
57
+ ns = all_objects.select {|o| o.type == :module || o.type == :class }
58
+ all_namespaces = {
59
+ :objects => ns.sort_by {|o| o.path },
60
+ :root => all_objects.find {|o| o.type == :root && (!o.meths.empty? || !o.constants.empty?) }
61
+ }
62
+ all_methods = { :objects => methods_to_show(all_objects) }
63
+
43
64
  serializer.serialize 'index.html', render(:index)
44
- serializer.serialize 'all-namespaces.html', render(:all_namespaces)
45
- serializer.serialize 'all-methods.html', render(:all_methods)
65
+ serializer.serialize 'all-files.html', render(:all_files)
66
+ serializer.serialize 'all-namespaces.html', render(:all_namespaces, all_namespaces)
67
+ serializer.serialize 'all-methods.html', render(:all_methods, all_methods)
46
68
  end
47
69
  true
48
70
  end
49
71
 
50
- def generate_readme
51
- if format == :html && serializer && readme_file
52
- @contents = File.read(readme_file)
53
- serializer.serialize 'readme.html', render(:readme)
72
+ def generate_files
73
+ if format == :html && serializer
74
+ extra_files.each do |file|
75
+ next unless File.exists?(file)
76
+ @contents = File.read(file)
77
+ file = File.basename(file)
78
+ serializer.serialize file + '.html', render(:file, :filename => file)
79
+ end
54
80
  end
55
81
  true
56
82
  end
83
+
84
+ def markup_for(filename)
85
+ case File.extname(filename).downcase
86
+ when /^\.(?:mdown|markdown|mkdn|markdn|md)$/
87
+ :markdown
88
+ when ".textile"
89
+ :textile
90
+ when /^\.html?$/
91
+ if format == :html
92
+ nil # no markup, use raw data
93
+ else
94
+ # TODO implement some html->plaintext markup
95
+ :rdoc
96
+ end
97
+ else
98
+ if @contents =~ /\A#!(\S+)\s*$/ # Shebang support
99
+ markup = $1
100
+ @contents.gsub!(/\A.+?\r?\n/, '')
101
+ markup.to_sym
102
+ else
103
+ :rdoc
104
+ end
105
+ end
106
+ end
107
+
108
+ def methods_to_show(namespaces)
109
+ meths = namespaces.inject([]) do |arr, namespace|
110
+ next(arr) unless namespace.is_a?(CodeObjects::NamespaceObject)
111
+ more_meths = namespace.meths(:included => false, :inherited => false)
112
+ more_meths = more_meths.select {|object| object.is_explicit? }
113
+ arr += more_meths
114
+ end
115
+ if options[:verifier]
116
+ meths.reject! do |object|
117
+ # FIXME we should be using call_verifier here, but visibility
118
+ # is checked on the generator, not the object
119
+ options[:verifier].call(object, object).is_a?(FalseClass)
120
+ end
121
+ end
122
+ meths.sort_by {|object| object.path }
123
+ end
57
124
  end
58
125
  end
59
- end
126
+ end