yard 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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
@@ -1,5 +1,5 @@
1
1
  module YARD
2
- module Parser
2
+ module Parser::Ruby::Legacy
3
3
  class Statement
4
4
  attr_reader :tokens, :comments, :block
5
5
 
@@ -9,8 +9,7 @@ module YARD
9
9
  @comments = comments
10
10
  end
11
11
 
12
- def inspect(lines = nil)
13
- flineno = tokens.first.line_no
12
+ def inspect
14
13
  buf = [""]
15
14
  tokens.each do |tk|
16
15
  if tk.is_a?(RubyToken::TkNL)
@@ -19,7 +18,12 @@ module YARD
19
18
  buf.last << tk.text
20
19
  end
21
20
  end
22
- buf.map {|line| "\t#{flineno}: #{line}" }.join("\n")
21
+ buf.map {|text| "\t#{line}: #{text}" }.join("\n")
22
+ end
23
+ alias show inspect
24
+
25
+ def line
26
+ tokens.first.line_no
23
27
  end
24
28
 
25
29
  private
@@ -0,0 +1,262 @@
1
+ module YARD
2
+ module Parser::Ruby::Legacy
3
+ class StatementList < Array
4
+ include RubyToken
5
+
6
+ # The following list of tokens will require a block to be opened
7
+ # if used at the beginning of a statement.
8
+ OPEN_BLOCK_TOKENS = [TkCLASS, TkDEF, TkMODULE, TkUNTIL,
9
+ TkIF, TkUNLESS, TkWHILE, TkFOR, TkCASE]
10
+
11
+ ##
12
+ # Creates a new statement list
13
+ #
14
+ # @param [TokenList, String] content the tokens to create the list from
15
+ def initialize(content)
16
+ if content.is_a? TokenList
17
+ @tokens = content.dup
18
+ elsif content.is_a? String
19
+ @tokens = TokenList.new(content)
20
+ else
21
+ raise ArgumentError, "Invalid content for StatementList: #{content.inspect}:#{content.class}"
22
+ end
23
+
24
+ parse_statements
25
+ end
26
+
27
+ def enumerator
28
+ self
29
+ end
30
+
31
+ private
32
+
33
+ def parse_statements
34
+ while stmt = next_statement do self << stmt end
35
+ end
36
+
37
+ ##
38
+ # Returns the next statement in the token stream
39
+ #
40
+ # @return [Statement] the next statement
41
+ def next_statement
42
+ @state = :first_statement
43
+ @statement_stack = []
44
+ @level = 0
45
+ @done = false
46
+ @current_block = nil
47
+ @statement, @block, @comments = TokenList.new, nil, nil
48
+ @last_tk, @last_ns_tk, @before_last_tk = nil, nil, nil
49
+
50
+ while !@done && tk = @tokens.shift
51
+ process_token(tk)
52
+
53
+ @before_last_tk = @last_tk
54
+ @last_tk = tk # Save last token
55
+ @last_ns_tk = tk unless [TkSPACE, TkNL, TkEND_OF_SCRIPT].include? tk.class
56
+ end
57
+
58
+ # Return the code block with starting token and initial comments
59
+ # If there is no code in the block, return nil
60
+ @comments = @comments.compact if @comments
61
+ if @block || !@statement.empty?
62
+ Statement.new(@statement, @block, @comments)
63
+ else
64
+ nil
65
+ end
66
+ end
67
+
68
+ ##
69
+ # Processes a single token
70
+ #
71
+ # @param [RubyToken::Token] tk the token to process
72
+ def process_token(tk)
73
+ case @state
74
+ when :first_statement
75
+ return if process_initial_comment(tk)
76
+ return if @statement.empty? && [TkSPACE, TkNL, TkCOMMENT].include?(tk.class)
77
+ return if process_simple_block_opener(tk)
78
+ push_token(tk)
79
+ return if process_complex_block_opener(tk)
80
+
81
+ if balances?(tk)
82
+ process_statement_end(tk)
83
+ else
84
+ @state = :balance
85
+ end
86
+ when :balance
87
+ @statement << tk
88
+ return unless balances?(tk)
89
+ @state = :first_statement
90
+ process_statement_end(tk)
91
+ when :block_statement
92
+ push_token(tk)
93
+ return unless balances?(tk)
94
+ process_statement_end(tk)
95
+ when :pre_block
96
+ @current_block = nil
97
+ process_block_token(tk) unless tk.class == TkSEMICOLON
98
+ @state = :block
99
+ when :block; process_block_token(tk)
100
+ when :post_block
101
+ if tk.class == TkSPACE
102
+ @statement << tk
103
+ return
104
+ end
105
+
106
+ process_statement_end(tk)
107
+ @state = :block
108
+ end
109
+ end
110
+
111
+ ##
112
+ # Processes a token in a block
113
+ #
114
+ # @param [RubyToken::Token] tk the token to process
115
+ def process_block_token(tk)
116
+ @block << tk
117
+ return unless balances?(tk)
118
+ process_statement_end(tk)
119
+ end
120
+
121
+ ##
122
+ # Processes a comment token that comes before a statement
123
+ #
124
+ # @param [RubyToken::Token] tk the token to process
125
+ # @return [Boolean] whether or not +tk+ was processed as an initial comment
126
+ def process_initial_comment(tk)
127
+ return unless tk.class == TkCOMMENT
128
+
129
+ # Two new-lines in a row will destroy any comment blocks
130
+ if @last_tk.class == TkNL && @before_last_tk &&
131
+ (@before_last_tk.class == TkNL || @before_last_tk.class == TkSPACE)
132
+ @comments = nil
133
+ return
134
+ end
135
+
136
+ # Remove the "#" and up to 1 space before the text
137
+ # Since, of course, the convention is to have "# text"
138
+ # and not "#text", which I deem ugly (you heard it here first)
139
+ @comments ||= []
140
+ @comments << tk.text.gsub(/^#+\s{0,1}/, '')
141
+ @comments.pop if @comments.size == 1 && @comments.first =~ /^\s*$/
142
+ true
143
+ end
144
+
145
+ ##
146
+ # Processes a simple block-opening token;
147
+ # that is, a block opener such as +begin+ or +do+
148
+ # that isn't followed by an expression
149
+ #
150
+ # @param [RubyToken::Token] tk the token to process
151
+ def process_simple_block_opener(tk)
152
+ return unless [TkLBRACE, TkDO, TkBEGIN].include?(tk.class) &&
153
+ # Make sure hashes are parsed as hashes, not as blocks
154
+ (@last_ns_tk.nil? || @last_ns_tk.lex_state != EXPR_BEG)
155
+
156
+ @block = TokenList.new
157
+ @block << tk
158
+ @level += 1
159
+ @state = :block
160
+
161
+ true
162
+ end
163
+
164
+ ##
165
+ # Processes a complex block-opening token;
166
+ # that is, a block opener such as +while+ or +for+
167
+ # that is followed by an expression
168
+ #
169
+ # @param [RubyToken::Token] tk the token to process
170
+ def process_complex_block_opener(tk)
171
+ return unless OPEN_BLOCK_TOKENS.include?(tk.class)
172
+ return if @last_ns_tk.class == TkALIAS
173
+
174
+ @current_block = tk.class
175
+ @state = :block_statement
176
+
177
+ true
178
+ end
179
+
180
+ ##
181
+ # Processes a token that closes a statement
182
+ #
183
+ # @param [RubyToken::Token] tk the token to process
184
+ def process_statement_end(tk)
185
+ # Whitespace means that we keep the same value of @new_statement as last token
186
+ return if tk.class == TkSPACE
187
+
188
+ return unless
189
+ # We might be coming after a statement-ending token...
190
+ ((@last_tk && [TkSEMICOLON, TkNL, TkEND_OF_SCRIPT].include?(tk.class)) ||
191
+ # Or we might be at the beginning of an argument list
192
+ (@current_block == TkDEF && tk.class == TkRPAREN))
193
+
194
+ # Continue a possible existing new statement unless we just finished an expression...
195
+ return unless (@last_tk && [EXPR_END, EXPR_ARG].include?(@last_tk.lex_state)) ||
196
+ # Or we've opened a block and are ready to move into the body
197
+ (@current_block && [TkNL, TkSEMICOLON].include?(tk.class) &&
198
+ # Handle the case where the block statement's expression is on the next line
199
+ #
200
+ # while
201
+ # foo
202
+ # end
203
+ @last_ns_tk.class != @current_block &&
204
+ # And the case where part of the expression is on the next line
205
+ #
206
+ # while foo ||
207
+ # bar
208
+ # end
209
+ @last_tk.lex_state != EXPR_BEG)
210
+
211
+ # Continue with the statement if we've hit a comma in a def
212
+ return if @current_block == TkDEF && peek_no_space.class == TkCOMMA
213
+
214
+ unless @current_block
215
+ @done = true
216
+ return
217
+ end
218
+
219
+ @level += 1
220
+ @state = :pre_block unless @stat == :block_statement
221
+ @block = TokenList.new
222
+ @block << tk if @current_block && tk.class == TkNL
223
+ end
224
+
225
+ ##
226
+ # Handles the balancing of parentheses and blocks
227
+ #
228
+ # @param [RubyToken::Token] tk the token to process
229
+ # @return [Boolean] whether or not the current statement's parentheses and blocks
230
+ # are balanced after +tk+
231
+ def balances?(tk)
232
+ if [TkLPAREN, TkLBRACK, TkLBRACE, TkDO, TkBEGIN].include?(tk.class)
233
+ @level += 1
234
+ elsif OPEN_BLOCK_TOKENS.include?(tk.class)
235
+ @level += 1 unless @last_ns_tk.class == TkALIAS
236
+ elsif [TkRPAREN, TkRBRACK, TkRBRACE, TkEND].include?(tk.class) && @level > 0
237
+ @level -= 1
238
+ end
239
+
240
+ @level == 0
241
+ end
242
+
243
+ ##
244
+ # Adds a token to the current statement,
245
+ # unless it's a newline, semicolon, or comment
246
+ #
247
+ # @param [RubyToken::Token] tk the token to process
248
+ def push_token(tk)
249
+ @statement << tk unless @level == 0 && [TkNL, TkSEMICOLON, TkCOMMENT].include?(tk.class)
250
+ end
251
+
252
+ ##
253
+ # Returns the next token in the stream that's not a space
254
+ #
255
+ # @return [RubyToken::Token] the next non-space token
256
+ def peek_no_space
257
+ return @tokens.first unless @tokens.first.class == TkSPACE
258
+ return @tokens[1]
259
+ end
260
+ end
261
+ end
262
+ end
@@ -1,5 +1,5 @@
1
1
  module YARD
2
- module Parser
2
+ module Parser::Ruby::Legacy
3
3
  class TokenList < Array
4
4
  include RubyToken
5
5
 
@@ -0,0 +1,307 @@
1
+ require 'ripper'
2
+
3
+ module YARD
4
+ module Parser
5
+ module Ruby
6
+ class ParserSyntaxError < UndocumentableError; end
7
+
8
+ class RubyParser < Ripper
9
+ attr_reader :ast, :charno, :comments, :file, :tokens
10
+ alias root ast
11
+
12
+ def initialize(source, filename, *args)
13
+ super
14
+ @file = filename
15
+ @source = source
16
+ @tokens = []
17
+ @comments = {}
18
+ @map = {}
19
+ @ns_charno = 0
20
+ @list = []
21
+ @charno = 0
22
+ end
23
+
24
+ def parse
25
+ @ast = super
26
+ @ast.full_source = @source
27
+ @ast.file = @file
28
+ freeze_tree
29
+ insert_comments
30
+ self
31
+ end
32
+
33
+ def enumerator
34
+ ast.children
35
+ end
36
+
37
+ private
38
+
39
+ MAPPINGS = {
40
+ :BEGIN => "BEGIN",
41
+ :END => "END",
42
+ :alias => "alias",
43
+ :array => :lbracket,
44
+ :aref => :lbracket,
45
+ :arg_paren => :lparen,
46
+ :begin => "begin",
47
+ :blockarg => "&",
48
+ :brace_block => :lbrace,
49
+ :break => "break",
50
+ :case => "case",
51
+ :class => "class",
52
+ :def => "def",
53
+ :defined => "defined?",
54
+ :defs => "def",
55
+ :do_block => "do",
56
+ :else => "else",
57
+ :elsif => "elsif",
58
+ :ensure => "ensure",
59
+ :for => "for",
60
+ :hash => :lbrace,
61
+ :if => "if",
62
+ :lambda => "lambda",
63
+ :module => "module",
64
+ :next => "next",
65
+ :paren => :lparen,
66
+ :qwords_literal => :qwords_beg,
67
+ :redo => "redo",
68
+ :regexp_literal => :regexp_beg,
69
+ :rescue => "rescue",
70
+ :rest_param => "*",
71
+ :retry => "retry",
72
+ :return => "return",
73
+ :return0 => "return",
74
+ :sclass => "class",
75
+ :string_embexpr => :embexpr_beg,
76
+ :string_literal => [:tstring_beg, :heredoc_beg],
77
+ :super => "super",
78
+ :symbol => :symbeg,
79
+ :undef => "undef",
80
+ :unless => "unless",
81
+ :until => "until",
82
+ :when => "when",
83
+ :while => "while",
84
+ :xstring_literal => :backtick,
85
+ :yield => "yield",
86
+ :yield0 => "yield",
87
+ :zsuper => "super"
88
+ }
89
+ REV_MAPPINGS = {}
90
+
91
+ AST_TOKENS = [:CHAR, :backref, :const, :cvar, :gvar, :heredoc_end, :ident,
92
+ :int, :float, :ivar, :period, :regexp_end, :tstring_content, :backtick]
93
+
94
+ MAPPINGS.each do |k, v|
95
+ if Array === v
96
+ v.each {|_v| (REV_MAPPINGS[_v] ||= []) << k }
97
+ else
98
+ (REV_MAPPINGS[v] ||= []) << k
99
+ end
100
+ end
101
+
102
+ PARSER_EVENT_TABLE.each do |event, arity|
103
+ node_class = AstNode.node_class_for(event)
104
+
105
+ if /_new\z/ =~ event and arity == 0
106
+ module_eval(<<-eof, __FILE__, __LINE__ + 1)
107
+ def on_#{event}(*args)
108
+ #{node_class}.new(:list, args, listchar: charno...charno, listline: lineno..lineno)
109
+ end
110
+ eof
111
+ elsif /_add(_.+)?\z/ =~ event
112
+ module_eval(<<-eof, __FILE__, __LINE__ + 1)
113
+ def on_#{event}(list, item)
114
+ list.push(item)
115
+ list
116
+ end
117
+ eof
118
+ elsif MAPPINGS.has_key?(event)
119
+ module_eval(<<-eof, __FILE__, __LINE__ + 1)
120
+ def on_#{event}(*args)
121
+ visit_event #{node_class}.new(:#{event}, args)
122
+ end
123
+ eof
124
+ else
125
+ module_eval(<<-eof, __FILE__, __LINE__ + 1)
126
+ def on_#{event}(*args)
127
+ #{node_class}.new(:#{event}, args, listline: lineno..lineno, listchar: charno...charno)
128
+ end
129
+ eof
130
+ end
131
+ end
132
+
133
+ SCANNER_EVENTS.each do |event|
134
+ ast_token = AST_TOKENS.include?(event)
135
+ module_eval(<<-eof, __FILE__, __LINE__ + 1)
136
+ def on_#{event}(tok)
137
+ visit_ns_token(:#{event}, tok, #{ast_token.inspect})
138
+ end
139
+ eof
140
+ end
141
+
142
+ REV_MAPPINGS.select {|k| k.is_a?(Symbol) }.each do |event, value|
143
+ ast_token = AST_TOKENS.include?(event)
144
+ module_eval(<<-eof, __FILE__, __LINE__ + 1)
145
+ def on_#{event}(tok)
146
+ (@map[:#{event}] ||= []) << [lineno, charno]
147
+ visit_ns_token(:#{event}, tok, #{ast_token.inspect})
148
+ end
149
+ eof
150
+ end
151
+
152
+ [:kw, :op].each do |event|
153
+ module_eval(<<-eof, __FILE__, __LINE__ + 1)
154
+ def on_#{event}(tok)
155
+ unless @tokens.last && @tokens.last[0] == :symbeg
156
+ (@map[tok] ||= []) << [lineno, charno]
157
+ end
158
+ visit_ns_token(:#{event}, tok, true)
159
+ end
160
+ eof
161
+ end
162
+
163
+ [:sp, :nl, :ignored_nl].each do |event|
164
+ module_eval(<<-eof, __FILE__, __LINE__ + 1)
165
+ def on_#{event}(tok)
166
+ add_token(:#{event}, tok)
167
+ @charno += tok.length
168
+ end
169
+ eof
170
+ end
171
+
172
+ def visit_event(node)
173
+ lstart, sstart = *@map[MAPPINGS[node.type]].pop
174
+ node.source_range = Range.new(sstart, @ns_charno - 1)
175
+ node.line_range = Range.new(lstart, lineno)
176
+ node
177
+ end
178
+
179
+ def visit_event_arr(node)
180
+ mapping = MAPPINGS[node.type].find {|k| @map[k] && !@map[k].empty? }
181
+ lstart, sstart = *@map[mapping].pop
182
+ node.source_range = Range.new(sstart, @ns_charno - 1)
183
+ node.line_range = Range.new(lstart, lineno)
184
+ node
185
+ end
186
+
187
+ def visit_ns_token(token, data, ast_token = false)
188
+ add_token(token, data)
189
+ ch = charno
190
+ @charno += data.length
191
+ @ns_charno = charno
192
+ if ast_token
193
+ AstNode.new(token, [data], line: lineno..lineno, char: ch..charno-1, token: true)
194
+ end
195
+ end
196
+
197
+ def add_token(token, data)
198
+ if @tokens.last && @tokens.last[0] == :symbeg
199
+ @tokens[-1] = [:symbol, ":" + data]
200
+ else
201
+ @tokens << [token, data]
202
+ end
203
+ end
204
+
205
+ def on_program(*args)
206
+ args.first
207
+ end
208
+
209
+ def on_body_stmt(*args)
210
+ args.first
211
+ end
212
+
213
+ def on_hash(*args)
214
+ visit_event AstNode.new(:hash, [args.first], listline: lineno..lineno, listchar: charno...charno)
215
+ end
216
+
217
+ def on_assoc_new(*args)
218
+ AstNode.new(:assoc, args)
219
+ end
220
+
221
+ def on_bare_assoc_hash(*args)
222
+ args.first
223
+ end
224
+
225
+ def on_assoclist_from_args(*args)
226
+ args.first
227
+ end
228
+
229
+ def on_qwords_new
230
+ visit_event AstNode.new(:qwords_literal, [])
231
+ end
232
+
233
+ def on_string_literal(*args)
234
+ visit_event_arr AstNode.new(:string_literal, args)
235
+ end
236
+
237
+ def on_string_content(*args)
238
+ AstNode.new(:string_content, args, listline: lineno..lineno, listchar: charno..charno)
239
+ end
240
+
241
+ def on_void_stmt
242
+ AstNode.new(:void_stmt, [], line: lineno..lineno, char: charno...charno)
243
+ end
244
+
245
+ def on_params(*args)
246
+ args.map! do |arg|
247
+ if arg.class == Array
248
+ if arg.first.class == Array
249
+ arg.map! do |sub_arg|
250
+ if sub_arg.class == Array
251
+ AstNode.new(:default_arg, sub_arg, listline: lineno..lineno, listchar: charno..charno)
252
+ else
253
+ sub_arg
254
+ end
255
+ end
256
+ end
257
+ AstNode.new(:list, arg, listline: lineno..lineno, listchar: charno..charno)
258
+ else
259
+ arg
260
+ end
261
+ end
262
+ ParameterNode.new(:params, args, listline: lineno..lineno, listchar: charno..charno)
263
+ end
264
+
265
+ def on_comment(comment)
266
+ visit_ns_token(:comment, comment)
267
+
268
+ comment = comment.gsub(/^\#{1,2}\s{0,1}/, '').chomp
269
+ append_comment = @comments[lineno - 1]
270
+
271
+ if append_comment
272
+ @comments.delete(lineno - 1)
273
+ comment = append_comment + "\n" + comment
274
+ end
275
+
276
+ @comments[lineno] = comment
277
+ end
278
+
279
+ def on_parse_error(msg)
280
+ raise ParserSyntaxError, "syntax error in `#{file}`:(#{lineno},#{column}): #{msg}"
281
+ end
282
+
283
+ def insert_comments
284
+ root.traverse do |node|
285
+ next if node.type == :list || node.parent.type != :list
286
+ node.line.downto(node.line - 2) do |line|
287
+ comment = @comments[line]
288
+ if comment && !comment.empty?
289
+ node.docstring = comment
290
+ comments.delete(line)
291
+ break
292
+ end
293
+ end
294
+ end
295
+ end
296
+
297
+ def freeze_tree(node = nil)
298
+ node ||= root
299
+ node.children.each do |child|
300
+ child.parent = node
301
+ freeze_tree(child)
302
+ end
303
+ end
304
+ end
305
+ end
306
+ end
307
+ end