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
@@ -69,9 +69,9 @@ module YARD
69
69
  #
70
70
  def included_meths_by_module
71
71
  all_meths = current_object.included_meths(:scope => scope, :visibility => visibility)
72
- current_object.mixins.each do |mixin|
72
+ current_object.mixins(scope).each do |mixin|
73
73
  next if mixin.is_a?(CodeObjects::Proxy)
74
- meths = mixin.meths(meths_opts).select {|c| all_meths.include?(c) }
74
+ meths = mixin.meths(meths_opts.merge(:scope => :instance)).select {|c| all_meths.include?(c) }
75
75
  remove_ignored_meths!(meths)
76
76
  next if meths.empty?
77
77
  yield(mixin, meths)
@@ -102,4 +102,4 @@ module YARD
102
102
  end
103
103
  end
104
104
  end
105
- end
105
+ end
@@ -1,15 +1,21 @@
1
1
  module YARD
2
2
  module Generators
3
3
  class MixinsGenerator < Base
4
+ attr_reader :scope
4
5
  before_generate :has_mixins?
6
+
7
+ def initialize(*args)
8
+ super
9
+ @scope = options[:scope]
10
+ end
5
11
 
6
12
  def sections_for(object) [:header] end
7
13
 
8
14
  protected
9
15
 
10
16
  def has_mixins?(object)
11
- !object.mixins.empty?
17
+ !object.mixins(@scope).empty?
12
18
  end
13
19
  end
14
20
  end
15
- end
21
+ end
@@ -7,7 +7,8 @@ module YARD
7
7
  [
8
8
  :header,
9
9
  [
10
- G(MixinsGenerator),
10
+ G(MixinsGenerator, :scope => :class),
11
+ G(MixinsGenerator, :scope => :instance),
11
12
  G(DocstringGenerator),
12
13
  G(AttributesGenerator),
13
14
  G(ConstantsGenerator),
@@ -19,4 +20,4 @@ module YARD
19
20
  end
20
21
  end
21
22
  end
22
- end
23
+ end
@@ -0,0 +1,20 @@
1
+ module YARD
2
+ module Generators
3
+ class OverloadsGenerator < Base
4
+ before_generate :has_overloads?
5
+
6
+ def sections_for(object)
7
+ [
8
+ :header,
9
+ [G(MethodGenerator)]
10
+ ]
11
+ end
12
+
13
+ protected
14
+
15
+ def has_overloads?(object)
16
+ object.tags(:overload).size > 1
17
+ end
18
+ end
19
+ end
20
+ end
@@ -5,14 +5,8 @@ module YARD
5
5
  case object
6
6
  when CodeObjects::MethodObject
7
7
  [
8
- :header,
9
- [
10
- G(DeprecatedGenerator),
11
- G(DocstringGenerator),
12
- G(MethodSignatureGenerator),
13
- G(TagsGenerator),
14
- G(SourceGenerator)
15
- ]
8
+ :header,
9
+ [G(MethodGenerator)]
16
10
  ]
17
11
  when CodeObjects::NamespaceObject
18
12
  [
@@ -28,4 +22,4 @@ module YARD
28
22
  end
29
23
  end
30
24
  end
31
- end
25
+ end
@@ -0,0 +1,32 @@
1
+ module YARD
2
+ module Generators
3
+ class RootGenerator < Base
4
+ before_generate :is_root?
5
+ before_generate :has_data?
6
+
7
+ def sections_for(object)
8
+ [
9
+ :header,
10
+ [
11
+ G(MixinsGenerator, :scope => :class),
12
+ G(MixinsGenerator, :scope => :instance),
13
+ G(ConstantsGenerator),
14
+ G(VisibilityGroupGenerator, :visibility => :public),
15
+ G(VisibilityGroupGenerator, :visibility => :protected),
16
+ G(VisibilityGroupGenerator, :visibility => :private)
17
+ ]
18
+ ]
19
+ end
20
+
21
+ private
22
+
23
+ def has_data?(object)
24
+ object.meths.size > 0 || object.constants.size > 0
25
+ end
26
+
27
+ def is_root?(object)
28
+ object == Registry.root
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,26 +1,11 @@
1
1
  module YARD
2
2
  module Generators
3
3
  class SourceGenerator < Base
4
+ include Helpers::MethodHelper
5
+
4
6
  def sections_for(object)
5
7
  [:main] if object.source
6
8
  end
7
-
8
- protected
9
-
10
- def format_lines(object)
11
- i = -1
12
- object.source.split(/\n/).map { object.line + (i += 1) }.join("\n")
13
- end
14
-
15
- def format_code(object, show_lines = false)
16
- i = -1
17
- lines = object.source.split(/\n/)
18
- longestline = (object.line + lines.size).to_s.length
19
- lines.map do |line|
20
- lineno = object.line + (i += 1)
21
- (" " * (longestline - lineno.to_s.length)) + lineno.to_s + " " + line
22
- end.join("\n")
23
- end
24
9
  end
25
10
  end
26
11
  end
@@ -1,20 +1,26 @@
1
1
  module YARD
2
2
  module Generators
3
3
  class TagsGenerator < Base
4
- before_section :header, :has_tags?
4
+ before_section :header, :has_tags?
5
+ before_section :option, :has_options?
6
+ before_section :param, :has_params?
5
7
 
6
8
  def sections_for(object)
7
- [:header, [:param, :yieldparam, :return, :raise, :author, :version, :since, :see]]
9
+ [:header, [:example, :param, :yield, :yieldparam, :yieldreturn, :return, :raise, :todo, :author, :version, :since, :see]]
8
10
  end
9
11
 
10
- def param(object)
11
- render_tags :param
12
+ def yield(object)
13
+ render_tags :yield
12
14
  end
13
15
 
14
16
  def yieldparam(object)
15
17
  render_tags :yieldparam
16
18
  end
17
-
19
+
20
+ def yieldreturn(object)
21
+ render_tags :yieldreturn
22
+ end
23
+
18
24
  def return(object)
19
25
  render_tags :return
20
26
  end
@@ -37,14 +43,36 @@ module YARD
37
43
 
38
44
  protected
39
45
 
46
+ def has_params?(object)
47
+ object.is_a?(CodeObjects::MethodObject) && tags_by_param(object).size > 0
48
+ end
49
+
40
50
  def has_tags?(object)
41
51
  object.tags.size > 0
42
52
  end
43
53
 
54
+ def has_options?(object)
55
+ object.has_tag?(:option)
56
+ end
57
+
44
58
  def render_tags(name, opts = {})
45
59
  opts = { :name => name }.update(opts)
46
60
  render(current_object, 'tags', opts)
47
61
  end
62
+
63
+ def tags_by_param(object)
64
+ cache = {}
65
+ [:param, :option].each do |sym|
66
+ object.tags(sym).each do |t|
67
+ cache[t.name.to_s] = t
68
+ end
69
+ end
70
+
71
+ object.parameters.map do |p|
72
+ name = p.first.to_s
73
+ cache[name] || cache[name[/^[*&](\w+)$/, 1]]
74
+ end.compact
75
+ end
48
76
  end
49
77
  end
50
- end
78
+ end
@@ -60,22 +60,32 @@ module YARD
60
60
 
61
61
  def process_objects(object)
62
62
  @objects[object.path] = object
63
- @objects[object.superclass.path] = object.superclass if object.is_a?(CodeObjects::ClassObject)
63
+ @objects[object.superclass.path] = object.superclass if object.is_a?(CodeObjects::ClassObject) && object.superclass
64
64
  object.mixins.each {|o| @objects[o.path] = o }
65
65
 
66
66
  namespaces(object).each {|o| process_objects(o) }
67
67
  end
68
68
 
69
- def method_list(object)
69
+ def method_list(object, attributes = false)
70
70
  vissort = lambda {|vis| vis == :public ? 'a' : (vis == :protected ? 'b' : 'c') }
71
71
 
72
- object.meths(:inherited => false, :included => false, :visibility => options[:visibility]).reject do |o|
73
- o.is_attribute?
74
- end.sort_by {|o| "#{o.scope}#{vissort.call(o.visibility)}#{o.name}" }
72
+ meths = object.meths(:inherited => false, :included => false, :visibility => options[:visibility])
73
+ meths = remove_overriden_meths(object, meths)
74
+ meths = meths.select {|o| attributes ? o.is_attribute? : !o.is_attribute? }
75
+ meths = meths.reject {|o| o.is_alias? }
76
+ meths = meths.sort_by {|o| "#{o.scope}#{vissort.call(o.visibility)}#{o.name}" }
75
77
  end
76
78
 
77
79
  private
78
80
 
81
+ def remove_overriden_meths(object, meth_list)
82
+ object.inheritance_tree(true)[1..-1].each do |sclass|
83
+ next if CodeObjects::Proxy === sclass
84
+ meth_list.reject! {|o| sclass.child(:scope => o.scope, :name => o.name) }
85
+ end
86
+ meth_list
87
+ end
88
+
79
89
  def tidy(data)
80
90
  indent = 0
81
91
  data.split(/\n/).map do |line|
@@ -89,4 +99,4 @@ module YARD
89
99
  end
90
100
  end
91
101
  end
92
- end
102
+ end
@@ -1,6 +1,9 @@
1
1
  module YARD
2
2
  module Handlers
3
- class UndocumentableError < Exception; end
3
+ class NamespaceMissingError < Parser::UndocumentableError
4
+ attr_accessor :object
5
+ def initialize(object) @object = object end
6
+ end
4
7
 
5
8
  # = Handlers
6
9
  #
@@ -33,7 +36,7 @@ module YARD
33
36
  # A Handler is automatically registered when it is subclassed from the
34
37
  # base class. The only other thing that needs to be done is to specify
35
38
  # which statement the handler will process. This is done with the +handles+
36
- # declaration, taking either a {Parser::RubyToken}, {String} or {Regexp}.
39
+ # declaration, taking either a {Parser::Ruby::Legacy::RubyToken}, {String} or `Regexp`.
37
40
  # Here is a simple example which processes module statements.
38
41
  #
39
42
  # class MyModuleHandler < YARD::Handlers::Base
@@ -53,10 +56,10 @@ module YARD
53
56
  #
54
57
  # === +statement+ Attribute
55
58
  #
56
- # The +statement+ attribute pertains to the {Parser::Statement} object
59
+ # The +statement+ attribute pertains to the {Parser::Ruby::Legacy::Statement} object
57
60
  # containing a set of tokens parsed in by the parser. This is the main set
58
61
  # of data to be analyzed and processed. The comments attached to the statement
59
- # can be accessed by the {Parser::Statement#comments} method, but generally
62
+ # can be accessed by the {Parser::Ruby::Legacy::Statement#comments} method, but generally
60
63
  # the data to be processed will live in the +tokens+ attribute. This list
61
64
  # can be converted to a +String+ using +#to_s+ to parse the data with
62
65
  # regular expressions (or other text processing mechanisms), if needed.
@@ -131,14 +134,11 @@ module YARD
131
134
  # @see #parse_block
132
135
  #
133
136
  class Base
134
- attr_accessor :__context__
135
-
136
137
  # For accessing convenience, eg. "MethodObject"
137
138
  # instead of the full qualified namespace
138
139
  include YARD::CodeObjects
139
140
 
140
- # For tokens like TkDEF, TkCLASS, etc.
141
- include YARD::Parser::RubyToken
141
+ include Parser
142
142
 
143
143
  class << self
144
144
  def clear_subclasses
@@ -146,7 +146,7 @@ module YARD
146
146
  end
147
147
 
148
148
  def subclasses
149
- @@subclasses || []
149
+ @@subclasses ||= []
150
150
  end
151
151
 
152
152
  def inherited(subclass)
@@ -164,7 +164,7 @@ module YARD
164
164
  # the handlers, otherwise the same code will be parsed
165
165
  # multiple times and slow YARD down.
166
166
  #
167
- # @param [Parser::RubyToken, String, Regexp] match
167
+ # @param [Parser::RubyToken, Symbol, String, Regexp] matches
168
168
  # statements that match the declaration will be
169
169
  # processed by this handler. A {String} match is
170
170
  # equivalent to a +/\Astring/+ regular expression
@@ -172,19 +172,24 @@ module YARD
172
172
  # token matches match only the first token of the
173
173
  # statement.
174
174
  #
175
- def handles(match)
176
- @handler = match
175
+ def handles(*matches)
176
+ (@handlers ||= []).push(*matches)
177
177
  end
178
178
 
179
- def handles?(tokens)
180
- case @handler
181
- when String
182
- tokens.first.text == @handler
183
- when Regexp
184
- tokens.to_s =~ @handler ? true : false
185
- else
186
- @handler == tokens.first.class
187
- end
179
+ def handles?(statement)
180
+ raise NotImplementedError, "override #handles? in a subclass"
181
+ end
182
+
183
+ def handlers
184
+ @handlers ||= []
185
+ end
186
+
187
+ def namespace_only
188
+ @namespace_only = true
189
+ end
190
+
191
+ def namespace_only?
192
+ @namespace_only ? true : false
188
193
  end
189
194
  end
190
195
 
@@ -213,11 +218,50 @@ module YARD
213
218
  raise NotImplementedError, "#{self} did not implement a #process method for handling."
214
219
  end
215
220
 
221
+ def parse_block(*args)
222
+ raise NotImplementedError, "#{self} did not implement a #parse_block method for handling"
223
+ end
224
+
216
225
  protected
217
226
 
218
227
  attr_reader :parser, :statement
219
228
  attr_accessor :owner, :namespace, :visibility, :scope
220
229
 
230
+ def owner; parser.owner end
231
+ def owner=(v) parser.owner=(v) end
232
+ def namespace; parser.namespace end
233
+ def namespace=(v); parser.namespace=(v) end
234
+ def visibility; parser.visibility end
235
+ def visibility=(v); parser.visibility=(v) end
236
+ def scope; parser.scope end
237
+ def scope=(v); parser.scope=(v) end
238
+
239
+ def push_state(opts = {}, &block)
240
+ opts = {
241
+ :namespace => nil,
242
+ :scope => :instance,
243
+ :owner => nil
244
+ }.update(opts)
245
+
246
+ if opts[:namespace]
247
+ ns, vis, sc = namespace, visibility, scope
248
+ self.namespace = opts[:namespace]
249
+ self.visibility = :public
250
+ self.scope = opts[:scope]
251
+ end
252
+
253
+ oldowner, self.owner = self.owner, opts[:owner] ? opts[:owner] : namespace
254
+ yield
255
+ self.owner = oldowner
256
+
257
+ if opts[:namespace]
258
+ self.namespace = ns
259
+ self.owner = namespace
260
+ self.visibility = vis
261
+ self.scope = sc
262
+ end
263
+ end
264
+
221
265
  # Do some post processing on a list of code objects.
222
266
  # Adds basic attributes to the list of objects like
223
267
  # the filename, line number, {CodeObjects::Base#dynamic},
@@ -234,7 +278,11 @@ module YARD
234
278
  objects.flatten.each do |object|
235
279
  next unless object.is_a?(CodeObjects::Base)
236
280
 
237
- ensure_namespace_loaded!(object)
281
+ begin
282
+ ensure_loaded!(object.namespace)
283
+ object.namespace.children << object
284
+ rescue NamespaceMissingError
285
+ end
238
286
 
239
287
  # Yield the object to the calling block because ruby will parse the syntax
240
288
  #
@@ -243,266 +291,53 @@ module YARD
243
291
  # as the block for #register. We need to make sure this gets to the object.
244
292
  yield(object) if block_given?
245
293
 
246
- # Add file and line number, but for class/modules this is
247
- # only done if there is a docstring for this specific definition.
248
- if (object.is_a?(NamespaceObject) && statement.comments) || !object.is_a?(NamespaceObject)
249
- object.file = parser.file
250
- object.line = statement.tokens.first.line_no
251
- elsif object.is_a?(NamespaceObject) && !statement.comments
252
- object.file ||= parser.file
253
- object.line ||= statement.tokens.first.line_no
254
- end
255
-
294
+ object.add_file(parser.file, statement.line, statement.comments)
295
+
256
296
  # Add docstring if there is one.
257
297
  object.docstring = statement.comments if statement.comments
258
298
 
259
299
  # Add source only to non-class non-module objects
260
300
  unless object.is_a?(NamespaceObject)
261
- object.source ||= statement
301
+ object.source ||= statement
262
302
  end
263
303
 
264
- # Make it dynamic if it's owner is not it's namespace.
304
+ # Make it dynamic if its owner is not its namespace.
265
305
  # This generally means it was defined in a method (or block of some sort)
266
306
  object.dynamic = true if owner != namespace
267
307
  end
268
308
  objects.size == 1 ? objects.first : objects
269
309
  end
270
-
271
- def parse_block(opts = nil)
272
- opts = {
273
- :namespace => nil,
274
- :scope => :instance,
275
- :owner => nil
276
- }.update(opts || {})
277
-
278
- if opts[:namespace]
279
- ns, vis, sc = namespace, visibility, scope
280
- self.namespace = opts[:namespace]
281
- self.visibility = :public
282
- self.scope = opts[:scope]
283
- end
284
-
285
- self.owner = opts[:owner] ? opts[:owner] : namespace
286
- parser.parse(statement.block) if statement.block
287
-
288
- if opts[:namespace]
289
- self.namespace = ns
290
- self.owner = namespace
291
- self.visibility = vis
292
- self.scope = sc
293
- end
294
- end
295
310
 
296
- def owner; @parser.owner end
297
- def owner=(v) @parser.owner=(v) end
298
- def namespace; @parser.namespace end
299
- def namespace=(v); @parser.namespace=(v) end
300
- def visibility; @parser.visibility end
301
- def visibility=(v); @parser.visibility=(v) end
302
- def scope; @parser.scope end
303
- def scope=(v); @parser.scope=(v) end
304
-
305
- def ensure_namespace_loaded!(object, max_retries = 1)
311
+ def ensure_loaded!(object, max_retries = 1)
306
312
  unless parser.load_order_errors
307
- return object.parent.is_a?(Proxy) ? load_order_warn(object.parent) : nil
313
+ if object.is_a?(Proxy)
314
+ raise NamespaceMissingError, object
315
+ else
316
+ nil
317
+ end
308
318
  end
309
319
 
310
- raise NotImplementedError if RUBY_PLATFORM =~ /java/
311
- return unless object.parent.is_a?(Proxy)
320
+ if RUBY_PLATFORM =~ /java/
321
+ log.warn "JRuby does not implement Kernel#callcc and cannot load files in order. You must specify the correct order manually."
322
+ raise NamespaceMissingError, object
323
+ end
312
324
 
313
325
  retries, context = 0, nil
314
326
  callcc {|c| context = c }
315
327
 
316
328
  retries += 1
317
329
 
318
- if object.parent.is_a?(Proxy)
330
+ if object.is_a?(Proxy)
319
331
  if retries <= max_retries
320
332
  log.debug "Missing object #{object.parent} in file `#{parser.file}', moving it to the back of the line."
321
333
  raise Parser::LoadOrderError, context
322
- end
323
-
324
- if retries > max_retries && !object.parent.is_a?(Proxy) && !BUILTIN_ALL.include?(object.path)
325
- load_order_warn(object.parent)
334
+ else
335
+ raise NamespaceMissingError, object
326
336
  end
327
337
  else
328
338
  log.debug "Object #{object} successfully resolved. Adding item to #{object.parent}'s children"
329
- object.namespace.children << object
330
- end
331
-
332
- rescue NotImplementedError
333
- log.warn "JRuby does not implement Kernel#callcc and cannot load files in order. You must specify the correct order manually."
334
- load_order_warn(object.parent)
335
- end
336
-
337
- def load_order_warn(object)
338
- log.warn "The #{object.type} #{object.path} has not yet been recognized."
339
- log.warn "If this class/method is part of your source tree, this will affect your documentation results."
340
- log.warn "You can correct this issue by loading the source file for this object before `#{parser.file}'"
341
- log.warn
342
- end
343
-
344
- # The string value of a token. For example, the return value for the symbol :sym
345
- # would be :sym. The return value for a string "foo #{bar}" would be the literal
346
- # "foo #{bar}" without any interpolation. The return value of the identifier
347
- # 'test' would be the same value: 'test'. Here is a list of common types and
348
- # their return values:
349
- #
350
- # @example
351
- # tokval(TokenList.new('"foo"').first) => "foo"
352
- # tokval(TokenList.new(':foo').first) => :foo
353
- # tokval(TokenList.new('CONSTANT').first, RubyToken::TkId) => "CONSTANT"
354
- # tokval(TokenList.new('identifier').first, RubyToken::TkId) => "identifier"
355
- # tokval(TokenList.new('3.25').first) => 3.25
356
- # tokval(TokenList.new('/xyz/i').first) => /xyz/i
357
- #
358
- # @param [Token] token The token of the class
359
- #
360
- # @param [Array<Class<Token>>, Symbol] accepted_types
361
- # The allowed token types that this token can be. Defaults to [{TkVal}].
362
- # A list of types would be, for example, [{TkSTRING}, {TkSYMBOL}], to return
363
- # the token's value if it is either of those types. If +TkVal+ is accepted,
364
- # +TkNode+ is also accepted.
365
- #
366
- # Certain symbol keys are allowed to specify multiple types in one fell swoop.
367
- # These symbols are:
368
- # :string => +TkSTRING+, +TkDSTRING+, +TkDXSTRING+ and +TkXSTRING+
369
- # :attr => +TkSYMBOL+ and +TkSTRING+
370
- # :identifier => +TkIDENTIFIER, +TkFID+ and +TkGVAR+.
371
- # :number => +TkFLOAT+, +TkINTEGER+
372
- #
373
- # @return [Object] if the token is one of the accepted types, in its real value form.
374
- # It should be noted that identifiers and constants are kept in String form.
375
- # @return [nil] if the token is not any of the specified accepted types
376
- def tokval(token, *accepted_types)
377
- accepted_types = [TkVal] if accepted_types.empty?
378
- accepted_types.push(TkNode) if accepted_types.include? TkVal
379
-
380
- if accepted_types.include?(:attr)
381
- accepted_types.push(TkSTRING, TkSYMBOL)
382
- end
383
-
384
- if accepted_types.include?(:string)
385
- accepted_types.push(TkSTRING, TkDSTRING, TkXSTRING, TkDXSTRING)
386
- end
387
-
388
- if accepted_types.include?(:identifier)
389
- accepted_types.push(TkIDENTIFIER, TkFID, TkGVAR)
390
- end
391
-
392
- if accepted_types.include?(:number)
393
- accepted_types.push(TkFLOAT, TkINTEGER)
394
- end
395
-
396
- return unless accepted_types.any? {|t| t === token }
397
-
398
- case token
399
- when TkSTRING, TkDSTRING, TkXSTRING, TkDXSTRING
400
- token.text[1..-2]
401
- when TkSYMBOL
402
- token.text[1..-1].to_sym
403
- when TkFLOAT
404
- token.text.to_f
405
- when TkINTEGER
406
- token.text.to_i
407
- when TkREGEXP
408
- token.text =~ /\A\/(.+)\/([^\/])\Z/
409
- Regexp.new($1, $2)
410
- when TkTRUE
411
- true
412
- when TkFALSE
413
- false
414
- when TkNIL
415
- nil
416
- else
417
- token.text
418
- end
419
- end
420
-
421
- # Returns a list of symbols or string values from a statement.
422
- # The list must be a valid comma delimited list, and values
423
- # will only be returned to the end of the list only.
424
- #
425
- # Example:
426
- # attr_accessor :a, 'b', :c, :d => ['a', 'b', 'c', 'd']
427
- # attr_accessor 'a', UNACCEPTED_TYPE, 'c' => ['a', 'c']
428
- #
429
- # The tokval list of a {TokenList} of the above
430
- # code would be the {#tokval} value of :a, 'b',
431
- # :c and :d.
432
- #
433
- # It should also be noted that this function stops immediately at
434
- # any ruby keyword encountered:
435
- # "attr_accessor :a, :b, :c if x == 5" => ['a', 'b', 'c']
436
- #
437
- # @param [TokenList] tokenlist The list of tokens to process.
438
- # @param [Array<Class<Token>>] accepted_types passed to {#tokval}
439
- # @return [Array<String>] the list of tokvalues in the list.
440
- # @return [Array<EMPTY>] if there are no symbols or Strings in the list
441
- # @see #tokval
442
- def tokval_list(tokenlist, *accepted_types)
443
- return [] unless tokenlist
444
- out = [[]]
445
- parencount, beforeparen = 0, 0
446
- needcomma = false
447
- seen_comma = true
448
- tokenlist.each do |token|
449
- tokval = tokval(token, *accepted_types)
450
- parencond = !out.last.empty? && tokval != nil
451
- #puts "#{seen_comma.inspect} #{parencount} #{token.class.class_name} #{out.inspect}"
452
- case token
453
- when TkCOMMA
454
- if parencount == 0
455
- out << [] unless out.last.empty?
456
- needcomma = false
457
- seen_comma = true
458
- else
459
- out.last << token.text if parencond
460
- end
461
- when TkLPAREN
462
- if seen_comma
463
- beforeparen += 1
464
- else
465
- parencount += 1
466
- out.last << token.text if parencond
467
- end
468
- when TkRPAREN
469
- if beforeparen > 0
470
- beforeparen -= 1
471
- else
472
- out.last << token.text if parencount > 0 && tokval != nil
473
- parencount -= 1
474
- end
475
- when TkLBRACE, TkLBRACK, TkDO
476
- parencount += 1
477
- out.last << token.text if tokval != nil
478
- when TkRBRACE, TkRBRACK, TkEND
479
- out.last << token.text if tokval != nil
480
- parencount -= 1
481
- else
482
- break if TkKW === token && ![TkTRUE, TkFALSE, TkSUPER, TkSELF, TkNIL].include?(token.class)
483
-
484
- seen_comma = false unless TkWhitespace === token
485
- if parencount == 0
486
- next if needcomma
487
- next if TkWhitespace === token
488
- if tokval != nil
489
- out.last << tokval
490
- else
491
- out.last.clear
492
- needcomma = true
493
- end
494
- elsif parencond
495
- needcomma = true
496
- out.last << token.text
497
- end
498
- end
499
-
500
- if beforeparen == 0 && parencount < 0
501
- break
502
- end
503
339
  end
504
- # Flatten any single element lists
505
- out.map {|e| e.empty? ? nil : (e.size == 1 ? e.pop : e.flatten.join) }.compact
340
+ object
506
341
  end
507
342
  end
508
343
  end