yard 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of yard might be problematic. Click here for more details.

Files changed (264) hide show
  1. data/{LICENSE.txt → LICENSE} +1 -1
  2. data/README +211 -0
  3. data/Rakefile +31 -0
  4. data/benchmarks/builtins_vs_eval.rb +23 -0
  5. data/benchmarks/erb_vs_erubis.rb +53 -0
  6. data/benchmarks/generation.rb +37 -0
  7. data/benchmarks/parsing.rb +33 -0
  8. data/bin/view_generator +17 -0
  9. data/bin/yard-graph +4 -0
  10. data/bin/yardoc +1 -93
  11. data/bin/yri +12 -3
  12. data/lib/yard.rb +10 -5
  13. data/lib/yard/autoload.rb +116 -0
  14. data/lib/yard/cli/yard_graph.rb +86 -0
  15. data/lib/yard/cli/yardoc.rb +131 -0
  16. data/lib/yard/code_objects/base.rb +321 -0
  17. data/lib/yard/code_objects/class_object.rb +89 -0
  18. data/lib/yard/code_objects/class_variable_object.rb +4 -0
  19. data/lib/yard/code_objects/constant_object.rb +4 -0
  20. data/lib/yard/code_objects/method_object.rb +51 -0
  21. data/lib/yard/code_objects/module_object.rb +4 -0
  22. data/lib/yard/code_objects/namespace_object.rb +88 -0
  23. data/lib/yard/code_objects/proxy.rb +183 -0
  24. data/lib/yard/code_objects/root_object.rb +8 -0
  25. data/lib/yard/core_ext/file.rb +26 -0
  26. data/lib/yard/core_ext/logger.rb +5 -0
  27. data/lib/yard/core_ext/module.rb +9 -0
  28. data/lib/yard/core_ext/string.rb +13 -0
  29. data/lib/yard/core_ext/symbol_hash.rb +24 -0
  30. data/lib/yard/generators/attributes_generator.rb +22 -0
  31. data/lib/yard/generators/base.rb +285 -0
  32. data/lib/yard/generators/class_generator.rb +25 -0
  33. data/lib/yard/generators/constants_generator.rb +73 -0
  34. data/lib/yard/generators/constructor_generator.rb +25 -0
  35. data/lib/yard/generators/deprecated_generator.rb +15 -0
  36. data/lib/yard/generators/docstring_generator.rb +15 -0
  37. data/lib/yard/generators/full_doc_generator.rb +59 -0
  38. data/lib/yard/generators/helpers/base_helper.rb +52 -0
  39. data/lib/yard/generators/helpers/filter_helper.rb +21 -0
  40. data/lib/yard/generators/helpers/html_helper.rb +137 -0
  41. data/lib/yard/generators/helpers/method_helper.rb +27 -0
  42. data/lib/yard/generators/helpers/uml_helper.rb +16 -0
  43. data/lib/yard/generators/inheritance_generator.rb +16 -0
  44. data/lib/yard/generators/method_details_generator.rb +18 -0
  45. data/lib/yard/generators/method_generator.rb +31 -0
  46. data/lib/yard/generators/method_listing_generator.rb +105 -0
  47. data/lib/yard/generators/method_missing_generator.rb +25 -0
  48. data/lib/yard/generators/method_signature_generator.rb +19 -0
  49. data/lib/yard/generators/method_summary_generator.rb +21 -0
  50. data/lib/yard/generators/mixins_generator.rb +15 -0
  51. data/lib/yard/generators/module_generator.rb +22 -0
  52. data/lib/yard/generators/quick_doc_generator.rb +31 -0
  53. data/lib/yard/generators/source_generator.rb +26 -0
  54. data/lib/yard/generators/tags_generator.rb +50 -0
  55. data/lib/yard/generators/uml_generator.rb +92 -0
  56. data/lib/yard/generators/visibility_group_generator.rb +26 -0
  57. data/lib/yard/handlers/alias_handler.rb +32 -0
  58. data/lib/yard/handlers/attribute_handler.rb +54 -0
  59. data/lib/yard/handlers/base.rb +509 -0
  60. data/lib/yard/handlers/class_handler.rb +44 -0
  61. data/lib/yard/handlers/class_variable_handler.rb +13 -0
  62. data/lib/yard/handlers/constant_handler.rb +13 -0
  63. data/lib/yard/handlers/exception_handler.rb +12 -0
  64. data/lib/yard/handlers/method_handler.rb +27 -0
  65. data/lib/yard/handlers/mixin_handler.rb +16 -0
  66. data/lib/yard/handlers/module_handler.rb +9 -0
  67. data/lib/yard/handlers/visibility_handler.rb +14 -0
  68. data/lib/yard/handlers/yield_handler.rb +26 -0
  69. data/lib/yard/logging.rb +27 -0
  70. data/lib/yard/parser/ruby_lex.rb +1344 -0
  71. data/lib/yard/parser/source_parser.rb +109 -0
  72. data/lib/yard/parser/statement.rb +36 -0
  73. data/lib/yard/parser/statement_list.rb +167 -0
  74. data/lib/yard/parser/token_list.rb +58 -0
  75. data/lib/yard/rake/yardoc_task.rb +30 -0
  76. data/lib/yard/registry.rb +136 -0
  77. data/lib/yard/serializers/base.rb +16 -0
  78. data/lib/yard/serializers/file_system_serializer.rb +48 -0
  79. data/lib/yard/serializers/process_serializer.rb +14 -0
  80. data/lib/yard/serializers/stdout_serializer.rb +21 -0
  81. data/lib/yard/tags/default_factory.rb +98 -0
  82. data/lib/yard/tags/library.rb +109 -0
  83. data/lib/yard/tags/merbdoc_factory.rb +47 -0
  84. data/lib/yard/tags/tag.rb +35 -0
  85. data/spec/code_objects/base_spec.rb +219 -0
  86. data/spec/code_objects/class_object_spec.rb +176 -0
  87. data/spec/code_objects/code_object_list_spec.rb +33 -0
  88. data/spec/code_objects/constants_spec.rb +79 -0
  89. data/spec/code_objects/method_object_spec.rb +30 -0
  90. data/spec/code_objects/module_object_spec.rb +73 -0
  91. data/spec/code_objects/namespace_object_spec.rb +129 -0
  92. data/spec/code_objects/proxy_spec.rb +80 -0
  93. data/spec/code_objects/spec_helper.rb +3 -0
  94. data/spec/core_ext/file_spec.rb +20 -0
  95. data/spec/core_ext/string_spec.rb +4 -0
  96. data/spec/core_ext/symbol_hash_spec.rb +80 -0
  97. data/spec/generators/base_spec.rb +64 -0
  98. data/spec/generators/helpers/base_helper_spec.rb +15 -0
  99. data/spec/generators/helpers/html_helper_spec.rb +56 -0
  100. data/spec/generators/quick_doc_generator_spec.rb +13 -0
  101. data/spec/handlers/alias_handler_spec.rb +50 -0
  102. data/spec/handlers/attribute_handler_spec.rb +78 -0
  103. data/spec/handlers/base_spec.rb +165 -0
  104. data/spec/handlers/class_handler_spec.rb +68 -0
  105. data/spec/handlers/class_variable_handler_spec.rb +9 -0
  106. data/spec/handlers/constant_handler_spec.rb +13 -0
  107. data/spec/handlers/examples/alias_handler_001.rb.txt +24 -0
  108. data/spec/handlers/examples/attribute_handler_001.rb.txt +19 -0
  109. data/spec/handlers/examples/class_handler_001.rb.txt +39 -0
  110. data/spec/handlers/examples/class_variable_handler_001.rb.txt +9 -0
  111. data/spec/handlers/examples/constant_handler_001.rb.txt +10 -0
  112. data/spec/handlers/examples/exception_handler_001.rb.txt +42 -0
  113. data/spec/handlers/examples/method_handler_001.rb.txt +35 -0
  114. data/spec/handlers/examples/mixin_handler_001.rb.txt +12 -0
  115. data/spec/handlers/examples/module_handler_001.rb.txt +16 -0
  116. data/spec/handlers/examples/visibility_handler_001.rb.txt +20 -0
  117. data/spec/handlers/examples/yield_handler_001.rb.txt +55 -0
  118. data/spec/handlers/exception_handler_spec.rb +35 -0
  119. data/spec/handlers/method_handler_spec.rb +35 -0
  120. data/spec/handlers/mixin_handler_spec.rb +30 -0
  121. data/spec/handlers/module_handler_spec.rb +25 -0
  122. data/spec/handlers/spec_helper.rb +21 -0
  123. data/spec/handlers/visibility_handler_spec.rb +24 -0
  124. data/spec/handlers/yield_handler_spec.rb +51 -0
  125. data/spec/parser/examples/example1.rb.txt +8 -0
  126. data/spec/parser/examples/tag_handler_001.rb.txt +8 -0
  127. data/spec/parser/source_parser_spec.rb +43 -0
  128. data/spec/parser/tag_parsing_spec.rb +18 -0
  129. data/spec/parser/token_list_spec.rb +35 -0
  130. data/spec/registry_spec.rb +70 -0
  131. data/spec/serializers/file_system_serializer_spec.rb +91 -0
  132. data/spec/serializers/spec_helper.rb +2 -0
  133. data/spec/spec_helper.rb +77 -0
  134. data/templates/default/attributes/html/header.erb +35 -0
  135. data/templates/default/attributes/text/header.erb +10 -0
  136. data/templates/default/class/html/header.erb +4 -0
  137. data/templates/default/constants/html/constants.erb +9 -0
  138. data/templates/default/constants/html/header.erb +3 -0
  139. data/templates/default/constants/html/included.erb +9 -0
  140. data/templates/default/constants/html/inherited.erb +9 -0
  141. data/templates/default/constructor/html/header.erb +10 -0
  142. data/templates/default/deprecated/html/main.erb +4 -0
  143. data/templates/default/deprecated/text/main.erb +3 -0
  144. data/templates/default/docstring/html/main.erb +3 -0
  145. data/templates/default/docstring/text/main.erb +3 -0
  146. data/templates/default/fulldoc/html/all_methods.erb +25 -0
  147. data/templates/default/fulldoc/html/all_namespaces.erb +19 -0
  148. data/templates/default/fulldoc/html/app.js +18 -0
  149. data/templates/default/fulldoc/html/header.erb +15 -0
  150. data/templates/default/fulldoc/html/html_head.erb +3 -0
  151. data/templates/default/fulldoc/html/index.erb +18 -0
  152. data/templates/default/fulldoc/html/jquery.js +11 -0
  153. data/templates/default/fulldoc/html/readme.erb +15 -0
  154. data/templates/default/fulldoc/html/style.css +65 -0
  155. data/templates/default/fulldoc/html/syntax_highlight.css +21 -0
  156. data/templates/default/inheritance/html/header.erb +8 -0
  157. data/templates/default/inheritance/text/header.erb +3 -0
  158. data/templates/default/method/html/aliases.erb +6 -0
  159. data/templates/default/method/html/header.erb +3 -0
  160. data/templates/default/method/html/title.erb +3 -0
  161. data/templates/default/methoddetails/html/header.erb +8 -0
  162. data/templates/default/methoddetails/html/method_header.erb +3 -0
  163. data/templates/default/methodmissing/html/header.erb +12 -0
  164. data/templates/default/methodsignature/html/main.erb +8 -0
  165. data/templates/default/methodsignature/text/main.erb +5 -0
  166. data/templates/default/methodsummary/html/header.erb +5 -0
  167. data/templates/default/methodsummary/html/included.erb +9 -0
  168. data/templates/default/methodsummary/html/inherited.erb +9 -0
  169. data/templates/default/methodsummary/html/summary.erb +25 -0
  170. data/templates/default/methodsummary/text/header.erb +5 -0
  171. data/templates/default/methodsummary/text/included.erb +0 -0
  172. data/templates/default/methodsummary/text/inherited.erb +0 -0
  173. data/templates/default/methodsummary/text/summary.erb +3 -0
  174. data/templates/default/mixins/html/header.erb +4 -0
  175. data/templates/default/module/html/header.erb +4 -0
  176. data/templates/default/quickdoc/html/header.erb +15 -0
  177. data/templates/default/quickdoc/text/header.erb +12 -0
  178. data/templates/default/source/html/main.erb +15 -0
  179. data/templates/default/source/text/main.erb +4 -0
  180. data/templates/default/tags/html/header.erb +4 -0
  181. data/templates/default/tags/html/see.erb +13 -0
  182. data/templates/default/tags/html/tags.erb +20 -0
  183. data/templates/default/tags/text/header.erb +3 -0
  184. data/templates/default/tags/text/see.erb +5 -0
  185. data/templates/default/tags/text/tags.erb +7 -0
  186. data/templates/default/uml/dot/child.erb +1 -0
  187. data/templates/default/uml/dot/dependencies.erb +10 -0
  188. data/templates/default/uml/dot/header.erb +6 -0
  189. data/templates/default/uml/dot/info.erb +14 -0
  190. data/templates/default/uml/dot/subgraph.erb +6 -0
  191. data/templates/default/uml/dot/superclasses.erb +9 -0
  192. data/templates/default/uml/dot/unknown.erb +3 -0
  193. data/templates/default/uml/dot/unknown_child.erb +1 -0
  194. data/templates/default/visibilitygroup/html/header.erb +6 -0
  195. data/templates/javadoc/attributes/html/header.erb +16 -0
  196. data/templates/javadoc/class/html/header.erb +4 -0
  197. data/templates/javadoc/constants/html/constants.erb +9 -0
  198. data/templates/javadoc/constants/html/header.erb +3 -0
  199. data/templates/javadoc/constants/html/included.erb +12 -0
  200. data/templates/javadoc/constants/html/inherited.erb +12 -0
  201. data/templates/javadoc/constructor/html/header.erb +10 -0
  202. data/templates/javadoc/deprecated/html/main.erb +0 -0
  203. data/templates/javadoc/docstring/html/main.erb +6 -0
  204. data/templates/javadoc/fulldoc/html/all_methods.erb +25 -0
  205. data/templates/javadoc/fulldoc/html/all_namespaces.erb +19 -0
  206. data/templates/javadoc/fulldoc/html/app.js +18 -0
  207. data/templates/javadoc/fulldoc/html/header.erb +15 -0
  208. data/templates/javadoc/fulldoc/html/html_head.erb +3 -0
  209. data/templates/javadoc/fulldoc/html/index.erb +18 -0
  210. data/templates/javadoc/fulldoc/html/jquery.js +11 -0
  211. data/templates/javadoc/fulldoc/html/readme.erb +15 -0
  212. data/templates/javadoc/fulldoc/html/style.css +22 -0
  213. data/templates/javadoc/fulldoc/html/syntax_highlight.css +21 -0
  214. data/templates/javadoc/inheritance/html/header.erb +6 -0
  215. data/templates/javadoc/method/html/aliases.erb +6 -0
  216. data/templates/javadoc/method/html/header.erb +4 -0
  217. data/templates/javadoc/method/html/title.erb +4 -0
  218. data/templates/javadoc/methoddetails/html/header.erb +8 -0
  219. data/templates/javadoc/methoddetails/html/method_header.erb +0 -0
  220. data/templates/javadoc/methodmissing/html/header.erb +12 -0
  221. data/templates/javadoc/methodsignature/html/main.erb +8 -0
  222. data/templates/javadoc/methodsummary/html/header.erb +5 -0
  223. data/templates/javadoc/methodsummary/html/included.erb +12 -0
  224. data/templates/javadoc/methodsummary/html/inherited.erb +12 -0
  225. data/templates/javadoc/methodsummary/html/summary.erb +25 -0
  226. data/templates/javadoc/mixins/html/header.erb +5 -0
  227. data/templates/javadoc/module/html/header.erb +4 -0
  228. data/templates/javadoc/source/html/main.erb +15 -0
  229. data/templates/javadoc/tags/html/header.erb +5 -0
  230. data/templates/javadoc/tags/html/see.erb +8 -0
  231. data/templates/javadoc/tags/html/tags.erb +19 -0
  232. data/templates/javadoc/visibilitygroup/html/header.erb +5 -0
  233. metadata +352 -50
  234. data/README.pdf +0 -0
  235. data/lib/code_object.rb +0 -337
  236. data/lib/extra.rb +0 -8
  237. data/lib/formatter.rb +0 -90
  238. data/lib/handlers/all_handlers.rb +0 -2
  239. data/lib/handlers/attribute_handler.rb +0 -51
  240. data/lib/handlers/class_handler.rb +0 -30
  241. data/lib/handlers/class_variable_handler.rb +0 -9
  242. data/lib/handlers/code_object_handler.rb +0 -104
  243. data/lib/handlers/constant_handler.rb +0 -11
  244. data/lib/handlers/exception_handler.rb +0 -20
  245. data/lib/handlers/method_handler.rb +0 -28
  246. data/lib/handlers/mixin_handler.rb +0 -15
  247. data/lib/handlers/module_handler.rb +0 -9
  248. data/lib/handlers/visibility_handler.rb +0 -7
  249. data/lib/handlers/yield_handler.rb +0 -33
  250. data/lib/logger.rb +0 -19
  251. data/lib/namespace.rb +0 -98
  252. data/lib/quick_doc.rb +0 -104
  253. data/lib/ruby_lex.rb +0 -1321
  254. data/lib/source_parser.rb +0 -253
  255. data/lib/tag_library.rb +0 -175
  256. data/lib/tag_type.rb +0 -155
  257. data/templates/default/html/_fulldoc.erb +0 -64
  258. data/templates/default/html/class.erb +0 -226
  259. data/templates/default/html/method.erb +0 -20
  260. data/templates/default/html/module.erb +0 -126
  261. data/test/fixtures/docstring.txt +0 -23
  262. data/test/fixtures/docstring2.txt +0 -4
  263. data/test/test_code_object.rb +0 -66
  264. data/test/test_namespace.rb +0 -10
@@ -0,0 +1,109 @@
1
+ require 'stringio'
2
+
3
+ module YARD
4
+ module Parser
5
+ class LoadOrderError < Exception; end
6
+
7
+ # Responsible for parsing a source file into the namespace
8
+ class SourceParser
9
+ class << self
10
+ def parse(paths = "lib/**/*.rb", level = log.level)
11
+ if paths.is_a?(Array)
12
+ files = paths.map {|p| Dir[p] }.flatten
13
+ else
14
+ files = Dir[File.join(Dir.pwd, paths)]
15
+ end
16
+
17
+ log.enter_level(level) do
18
+ parse_in_order(*files.uniq)
19
+ end
20
+ end
21
+
22
+ def parse_string(content)
23
+ new.parse(StringIO.new(content))
24
+ end
25
+
26
+ private
27
+
28
+ def parse_in_order(*files)
29
+ while file = files.shift
30
+ begin
31
+ if file.is_a?(Array) && file.last.is_a?(Continuation)
32
+ log.debug("Re-processing #{file.first}")
33
+ file.last.call
34
+ elsif file.is_a?(String)
35
+ log.debug("Processing #{file}...")
36
+ new(true).parse(file)
37
+ end
38
+ rescue LoadOrderError => e
39
+ # Out of order file. Push the context to the end and we'll call it
40
+ files.push([file, e.message])
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ attr_reader :file
47
+ attr_accessor :namespace, :visibility, :scope, :owner, :load_order_errors
48
+
49
+ def initialize(load_order_errors = false)
50
+ @file = "<STDIN>"
51
+ @namespace = YARD::Registry.root
52
+ @visibility = :public
53
+ @scope = :instance
54
+ @owner = @namespace
55
+ @load_order_errors = load_order_errors
56
+ end
57
+
58
+ ##
59
+ # Creates a new SourceParser that parses a file and returns
60
+ # analysis information about it.
61
+ #
62
+ # @param [String, TokenList, StatementList, #read] content the source file to parse
63
+ def parse(content = __FILE__)
64
+ case content
65
+ when String
66
+ @file = content
67
+ statements = StatementList.new(IO.read(content))
68
+ when TokenList
69
+ statements = StatementList.new(content)
70
+ when StatementList
71
+ statements = content
72
+ else
73
+ if content.respond_to? :read
74
+ statements = StatementList.new(content.read)
75
+ else
76
+ raise ArgumentError, "Invalid argument for SourceParser::parse: #{content.inspect}:#{content.class}"
77
+ end
78
+ end
79
+
80
+ top_level_parse(statements)
81
+ end
82
+
83
+ private
84
+ def top_level_parse(statements)
85
+ statements.each do |stmt|
86
+ find_handlers(stmt).each do |handler|
87
+ begin
88
+ handler.new(self, stmt).process
89
+ rescue LoadOrderError => loaderr
90
+ raise # Pass this up
91
+ rescue Handlers::UndocumentableError => undocerr
92
+ log.warn "in #{handler.to_s}: Undocumentable #{undocerr.message}"
93
+ log.warn "\tin file '#{file}':#{stmt.tokens.first.line_no}:\n\n" + stmt.inspect + "\n"
94
+ rescue => e
95
+ log.error "Unhandled exception in #{handler.to_s}:"
96
+ log.error "#{e.class.class_name}: #{e.message}"
97
+ log.error " in `#{file}`:#{stmt.tokens.first.line_no}:\n\n#{stmt.inspect}\n"
98
+ log.error "Stack trace:" + e.backtrace[0..5].map {|x| "\n\t#{x}" }.join + "\n"
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def find_handlers(stmt)
105
+ Handlers::Base.subclasses.find_all {|sub| sub.handles? stmt.tokens }
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,36 @@
1
+ module YARD
2
+ module Parser
3
+ class Statement
4
+ attr_reader :tokens, :comments, :block
5
+
6
+ def initialize(tokens, block = nil, comments = nil)
7
+ @tokens = tokens
8
+ @block = block
9
+ @comments = comments
10
+ end
11
+
12
+ def inspect(lines = nil)
13
+ flineno = tokens.first.line_no
14
+ buf = [""]
15
+ tokens.each do |tk|
16
+ if tk.is_a?(RubyToken::TkNL)
17
+ buf.push ""
18
+ else
19
+ buf.last << tk.text
20
+ end
21
+ end
22
+ buf.map {|line| "\t#{flineno}: #{line}" }.join("\n")
23
+ end
24
+
25
+ private
26
+ def clean_tokens(tokens)
27
+ last_tk = nil
28
+ tokens.reject do |tk|
29
+ tk.is_a?(RubyToken::TkNL) ||
30
+ (last_tk.is_a?(RubyToken::TkSPACE) &&
31
+ last_tk.class == tk.class) && last_tk = tk
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,167 @@
1
+ module YARD
2
+ module Parser
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
+ COLON_TOKENS = [TkUNTIL, TkIF, TkUNLESS, TkWHILE, TkCASE, TkWHEN]
11
+
12
+ ##
13
+ # Creates a new statement list
14
+ #
15
+ # @param [TokenList, String] content the tokens to create the list from
16
+ def initialize(content)
17
+ if content.is_a? TokenList
18
+ @tokens = content.dup
19
+ elsif content.is_a? String
20
+ @tokens = TokenList.new(content)
21
+ else
22
+ raise ArgumentError, "Invalid content for StatementList: #{content.inspect}:#{content.class}"
23
+ end
24
+
25
+ parse_statements
26
+ end
27
+
28
+ private
29
+
30
+ def parse_statements
31
+ while stmt = next_statement do self << stmt end
32
+ end
33
+
34
+ # MUST REFACTOR THIS CODE
35
+ # WARNING WARNING WARNING WARNING
36
+ # MUST REFACTOR THIS CODE |
37
+ # OR CHILDREN WILL DIE V
38
+ # WARNING WARNING WARNING WARNING
39
+ # THIS IS MEANT TO BE UGLY.
40
+ def next_statement
41
+ statement, block, comments = TokenList.new, nil, nil
42
+ stmt_number, level = 0, 0
43
+ new_statement, open_block = true, false
44
+ last_tk, last_ns_tk, before_last_tk = nil, nil, nil
45
+ open_parens = 0
46
+
47
+ while tk = @tokens.shift
48
+ #p tk.class
49
+ # !!!!!!!!!!!!!!!!!!!! REMOVED TkfLPAREN, TkfLBRACK
50
+ open_parens += 1 if [TkLPAREN, TkLBRACK].include? tk.class
51
+ open_parens -= 1 if [TkRPAREN, TkRBRACK].include?(tk.class)
52
+
53
+ #if open_parens < 0 || level < 0
54
+ # STDERR.puts block.to_s + " TOKEN #{tk.inspect}"
55
+ # exit
56
+ #end
57
+
58
+ # Get the initial comments
59
+ if statement.empty?
60
+ # Two new-lines in a row will destroy any comment blocks
61
+ if [TkCOMMENT].include?(tk.class) && last_tk.class == TkNL &&
62
+ (before_last_tk && (before_last_tk.class == TkNL || before_last_tk.class == TkSPACE))
63
+ comments = nil
64
+ elsif tk.class == TkCOMMENT
65
+ # Remove the "#" and up to 1 space before the text
66
+ # Since, of course, the convention is to have "# text"
67
+ # and not "#text", which I deem ugly (you heard it here first)
68
+ comments ||= []
69
+ comments << tk.text.gsub(/^#+\s{0,1}/, '')
70
+ comments.pop if comments.size == 1 && comments.first =~ /^\s*$/
71
+ end
72
+ end
73
+
74
+ # Ignore any initial comments or whitespace
75
+ unless statement.empty? && [TkSPACE, TkNL, TkCOMMENT].include?(tk.class)
76
+ # Decrease if end or '}' is seen
77
+ level -= 1 if [TkEND, TkRBRACE].include?(tk.class)
78
+
79
+ # If the level is greater than 0, add the code to the block text
80
+ # otherwise it's part of the statement text
81
+ if stmt_number > 0
82
+ #puts "Block of #{statement}"
83
+ #puts "#{stmt_number} #{tk.line_no} #{level} #{open_parens} #{tk.class.class_name} \t#{tk.text.inspect} #{tk.lex_state} #{open_block.inspect}"
84
+ block ||= TokenList.new
85
+ block << tk
86
+ elsif stmt_number == 0 && tk.class != TkNL && tk.class != TkSEMICOLON && tk.class != TkCOMMENT
87
+ statement << tk
88
+ end
89
+
90
+ #puts "#{tk.line_no} #{level} #{open_parens} #{tk.class.class_name} \t#{tk.text.inspect} #{tk.lex_state} #{open_block.inspect}"
91
+
92
+ # Increase level if we have a 'do' or block opening
93
+ if tk.class == TkLBRACE #|| tk.class == TkfLBRACE
94
+ level += 1
95
+ elsif [TkDO, TkBEGIN].include?(tk.class)
96
+ #p "#{tk.line_no} #{level} #{tk} \t#{tk.text} #{tk.lex_state}"
97
+ level += 1
98
+ open_block = false # Cancel our wish to open a block for the if, we're doing it now
99
+ end
100
+
101
+ # Vouch to open a block when this statement would otherwise end
102
+ open_block = [level, tk.class] if (new_statement ||
103
+ (last_tk && last_tk.lex_state == EXPR_BEG)) &&
104
+ OPEN_BLOCK_TOKENS.include?(tk.class)
105
+
106
+ # Check if this token creates a new statement or not
107
+ #puts "#{open_parens} open brackets for: #{statement.to_s}"
108
+ if open_parens == 0 && ((last_tk && [TkSEMICOLON, TkNL, TkEND_OF_SCRIPT].include?(tk.class)) ||
109
+ (open_block && open_block.last == TkDEF && tk.class == TkRPAREN))
110
+
111
+ # Make sure we don't have any running expressions
112
+ # This includes things like
113
+ #
114
+ # class <
115
+ # Foo
116
+ #
117
+ # if a ||
118
+ # b
119
+ if (last_tk && [EXPR_END, EXPR_ARG].include?(last_tk.lex_state)) ||
120
+ (open_block && [TkNL, TkSEMICOLON].include?(tk.class) && last_ns_tk.class != open_block.last)
121
+ stmt_number += 1
122
+ new_statement = true
123
+ #p "NEW STATEMENT #{block.to_s}"
124
+
125
+ # The statement started with a if/while/begin, so we must go to the next level now
126
+ if open_block && open_block.first == level
127
+ if tk.class == TkNL && block.nil?
128
+ block = TokenList.new
129
+ block << tk
130
+ end
131
+
132
+ open_block = false
133
+ level += 1
134
+ end
135
+ end
136
+ elsif tk.class != TkSPACE
137
+ new_statement = false
138
+ end
139
+
140
+ # Else keyword is kind of weird
141
+ if tk.is_a? TkELSE
142
+ new_statement = true
143
+ stmt_number += 1
144
+ open_block = false
145
+ end
146
+
147
+ # We're done if we've ended a statement and we're at level 0
148
+ break if new_statement && level == 0
149
+
150
+ #raise "Unexpected end" if level < 0
151
+ end
152
+
153
+ #break if new_statement && level == 0
154
+
155
+ before_last_tk = last_tk
156
+ last_tk = tk # Save last token
157
+ last_ns_tk = tk unless [TkSPACE, TkNL, TkEND_OF_SCRIPT].include? tk.class
158
+ end
159
+
160
+ # Return the code block with starting token and initial comments
161
+ # If there is no code in the block, return nil
162
+ comments = comments.compact if comments
163
+ statement.empty? ? nil : Statement.new(statement, block, comments)
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,58 @@
1
+ module YARD
2
+ module Parser
3
+ class TokenList < Array
4
+ include RubyToken
5
+
6
+ def initialize(content = nil)
7
+ self << content if content
8
+ end
9
+
10
+ def to_s
11
+ collect {|t| t.text }.join
12
+ end
13
+
14
+ # @param [TokenList, Token, String] tokens
15
+ # A list of tokens. If the token is a string, it
16
+ # is parsed with {RubyLex}.
17
+ def push(*tokens)
18
+ tokens.each do |tok|
19
+ if tok.is_a?(TokenList) || tok.is_a?(Array)
20
+ concat tok
21
+ elsif tok.is_a?(Token)
22
+ super tok
23
+ elsif tok.is_a?(String)
24
+ parse_content(tok)
25
+ else
26
+ raise ArgumentError, "Expecting token, list of tokens or string of code to be tokenized. Got #{tok.class}"
27
+ end
28
+ end
29
+ self
30
+ end
31
+ alias_method :<<, :push
32
+
33
+ def squeeze(type = TkSPACE)
34
+ last = nil
35
+ TokenList.new(map {|t| x = t.is_a?(type) && last.is_a?(type) ? nil : t; last = t; x })
36
+ end
37
+
38
+ private
39
+
40
+ def parse_content(content)
41
+ lex = RubyLex.new(content)
42
+ while tk = lex.token do
43
+ self << convert_token(lex, tk)
44
+ end
45
+ end
46
+
47
+ def convert_token(lex, tk)
48
+ if TkSYMBEG === tk && next_tk = lex.token
49
+ sym = TkSYMBOL.new(tk.line_no, tk.char_no, nil)
50
+ sym.lex_state = lex.lex_state
51
+ sym.set_text(tk.text + next_tk.text)
52
+ else
53
+ tk
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ module YARD
5
+ module Rake
6
+
7
+ class YardocTask < ::Rake::TaskLib
8
+ attr_accessor :name
9
+ attr_accessor :options
10
+ attr_accessor :files
11
+
12
+ def initialize(name = :yardoc)
13
+ @name = name
14
+ @options = []
15
+ @files = []
16
+
17
+ yield self if block_given?
18
+ self.options += ENV['OPTS'].split(/[ ,]/) if ENV['OPTS']
19
+ self.files += ENV['FILES'].split(/[ ,]/) if ENV['FILES']
20
+
21
+ define
22
+ end
23
+
24
+ def define
25
+ desc "Generate YARD Documentation"
26
+ task(name) { YARD::CLI::Yardoc.run *(options + files) }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,136 @@
1
+ require 'singleton'
2
+ require 'find'
3
+
4
+ module YARD
5
+ class Registry
6
+ DEFAULT_YARDOC_FILE = ".yardoc"
7
+
8
+ include Singleton
9
+
10
+ @objects = {}
11
+
12
+ class << self
13
+ attr_reader :objects
14
+
15
+ def method_missing(meth, *args, &block)
16
+ if instance.respond_to? meth
17
+ instance.send(meth, *args, &block)
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ def clear
24
+ instance.clear
25
+ objects.clear
26
+ end
27
+ end
28
+
29
+ attr_accessor :yardoc_file
30
+ attr_reader :proxy_types
31
+
32
+ def load(files = [], reload = false)
33
+ if files.is_a?(Array)
34
+ if File.exists?(yardoc_file) && !reload
35
+ load_yardoc
36
+ else
37
+ size = namespace.size
38
+ YARD.parse(files)
39
+ save if namespace.size > size
40
+ end
41
+ true
42
+ elsif files.is_a?(String)
43
+ load_yardoc(files)
44
+ true
45
+ else
46
+ raise ArgumentError, "Must take a list of files to parse or the .yardoc file to load."
47
+ end
48
+ end
49
+
50
+ def load_yardoc(file = yardoc_file)
51
+ return false unless File.exists?(file)
52
+ ns, pt = *Marshal.load(IO.read(file))
53
+ namespace.update(ns)
54
+ proxy_types.update(pt)
55
+ end
56
+
57
+ def save(file = yardoc_file)
58
+ File.open(file, "w") {|f| Marshal.dump([@namespace, @proxy_types], f) }
59
+ true
60
+ end
61
+
62
+ def all(*types)
63
+ namespace.values.select do |obj|
64
+ if types.empty?
65
+ obj != Registry.root
66
+ else
67
+ obj != Registry.root &&
68
+ types.any? do |type|
69
+ type.is_a?(Symbol) ? obj.type == type : obj.is_a?(type)
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def paths
76
+ namespace.keys.map {|k| k.to_s }
77
+ end
78
+
79
+ def at(path) path.to_s.empty? ? root : namespace[path] end
80
+ alias_method :[], :at
81
+
82
+ def root; namespace[:root] end
83
+ def delete(object) namespace.delete(object.path) end
84
+
85
+ def clear
86
+ @namespace = SymbolHash.new
87
+ @namespace[:root] = CodeObjects::RootObject.new(nil, :root)
88
+ @proxy_types = {}
89
+ end
90
+
91
+ def initialize
92
+ @yardoc_file = DEFAULT_YARDOC_FILE
93
+ clear
94
+ end
95
+
96
+ def register(object)
97
+ return if object.is_a?(CodeObjects::Proxy)
98
+ namespace[object.path] = object
99
+ end
100
+
101
+ def resolve(namespace, name, proxy_fallback = false)
102
+ namespace = root if namespace == :root || !namespace
103
+
104
+ newname = name.to_s.gsub(/^#{CodeObjects::ISEP}/, '')
105
+ if name =~ /^#{CodeObjects::NSEP}/
106
+ [name, newname[2..-1]].each do |n|
107
+ return at(n) if at(n)
108
+ end
109
+ else
110
+ while namespace
111
+ [CodeObjects::NSEP, CodeObjects::ISEP].each do |s|
112
+ path = newname
113
+ if namespace != root
114
+ path = [namespace.path, newname].join(s)
115
+ end
116
+ found = at(path)
117
+ return found if found
118
+ end
119
+ namespace = namespace.parent
120
+ end
121
+
122
+ # Look for ::name or #name in the root space
123
+ [CodeObjects::NSEP, CodeObjects::ISEP].each do |s|
124
+ found = at(s + newname)
125
+ return found if found
126
+ end
127
+ end
128
+ proxy_fallback ? CodeObjects::Proxy.new(namespace, name) : nil
129
+ end
130
+
131
+ private
132
+
133
+ attr_accessor :namespace
134
+
135
+ end
136
+ end