ruby-lint 0.0.2 → 0.0.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.
Files changed (321) hide show
  1. data.tar.gz.asc +17 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +25 -0
  4. data/.yardopts +4 -0
  5. data/Gemfile +1 -1
  6. data/LICENSE +1 -1
  7. data/MANIFEST +238 -49
  8. data/README.md +84 -131
  9. data/Rakefile +6 -0
  10. data/bin/ruby-lint +2 -2
  11. data/checksum/.gitkeep +0 -0
  12. data/doc/DCO.md +26 -0
  13. data/doc/architecture.md +63 -0
  14. data/doc/code_analysis.md +90 -0
  15. data/doc/configuration.md +86 -0
  16. data/doc/contributing.md +16 -0
  17. data/doc/graphviz/flow.dot +7 -0
  18. data/doc/images/.gitkeep +0 -0
  19. data/doc/images/flow.png +0 -0
  20. data/lib/ruby-lint.rb +35 -35
  21. data/lib/ruby-lint/analyze/argument_amount.rb +73 -0
  22. data/lib/ruby-lint/analyze/shadowing_variables.rb +19 -24
  23. data/lib/ruby-lint/analyze/undefined_methods.rb +68 -0
  24. data/lib/ruby-lint/analyze/undefined_variables.rb +42 -69
  25. data/lib/ruby-lint/analyze/unused_variables.rb +23 -78
  26. data/lib/ruby-lint/base.rb +85 -0
  27. data/lib/ruby-lint/cli.rb +23 -167
  28. data/lib/ruby-lint/cli/analyze.rb +99 -0
  29. data/lib/ruby-lint/cli/ast.rb +35 -0
  30. data/lib/ruby-lint/cli/base.rb +120 -0
  31. data/lib/ruby-lint/configuration.rb +112 -0
  32. data/lib/ruby-lint/constant_loader.rb +92 -0
  33. data/lib/ruby-lint/definition/ruby_method.rb +248 -0
  34. data/lib/ruby-lint/definition/ruby_object.rb +757 -0
  35. data/lib/ruby-lint/definition_generator.rb +155 -0
  36. data/lib/ruby-lint/definitions/core.rb +5 -0
  37. data/lib/ruby-lint/definitions/core/arg0.rb +7 -0
  38. data/lib/ruby-lint/definitions/core/argf.rb +7 -0
  39. data/lib/ruby-lint/definitions/core/argument_error.rb +12 -0
  40. data/lib/ruby-lint/definitions/core/argv.rb +7 -0
  41. data/lib/ruby-lint/definitions/core/array.rb +414 -0
  42. data/lib/ruby-lint/definitions/core/autoload.rb +39 -0
  43. data/lib/ruby-lint/definitions/core/basic_object.rb +46 -0
  44. data/lib/ruby-lint/definitions/core/bignum.rb +128 -0
  45. data/lib/ruby-lint/definitions/core/binding.rb +52 -0
  46. data/lib/ruby-lint/definitions/core/class.rb +23 -0
  47. data/lib/ruby-lint/definitions/core/comparable.rb +38 -0
  48. data/lib/ruby-lint/definitions/core/complex.rb +195 -0
  49. data/lib/ruby-lint/definitions/core/condition_variable.rb +19 -0
  50. data/lib/ruby-lint/definitions/core/continuation.rb +8 -0
  51. data/lib/ruby-lint/definitions/core/data.rb +8 -0
  52. data/lib/ruby-lint/definitions/core/date.rb +706 -0
  53. data/lib/ruby-lint/definitions/core/date_time.rb +381 -0
  54. data/lib/ruby-lint/definitions/core/default_record_separator.rb +7 -0
  55. data/lib/ruby-lint/definitions/core/digest.rb +166 -0
  56. data/lib/ruby-lint/definitions/core/dir.rb +496 -0
  57. data/lib/ruby-lint/definitions/core/encoding.rb +2030 -0
  58. data/lib/ruby-lint/definitions/core/encoding_error.rb +8 -0
  59. data/lib/ruby-lint/definitions/core/enumerable.rb +352 -0
  60. data/lib/ruby-lint/definitions/core/enumerator.rb +37 -0
  61. data/lib/ruby-lint/definitions/core/env.rb +7 -0
  62. data/lib/ruby-lint/definitions/core/eoferror.rb +8 -0
  63. data/lib/ruby-lint/definitions/core/erb.rb +304 -0
  64. data/lib/ruby-lint/definitions/core/errno.rb +3331 -0
  65. data/lib/ruby-lint/definitions/core/etc.rb +138 -0
  66. data/lib/ruby-lint/definitions/core/exception.rb +72 -0
  67. data/lib/ruby-lint/definitions/core/false.rb +7 -0
  68. data/lib/ruby-lint/definitions/core/false_class.rb +30 -0
  69. data/lib/ruby-lint/definitions/core/fatal_error.rb +8 -0
  70. data/lib/ruby-lint/definitions/core/fiber.rb +35 -0
  71. data/lib/ruby-lint/definitions/core/fiber_error.rb +8 -0
  72. data/lib/ruby-lint/definitions/core/file.rb +1277 -0
  73. data/lib/ruby-lint/definitions/core/file_list.rb +727 -0
  74. data/lib/ruby-lint/definitions/core/file_test.rb +106 -0
  75. data/lib/ruby-lint/definitions/core/file_utils.rb +1027 -0
  76. data/lib/ruby-lint/definitions/core/fixnum.rb +156 -0
  77. data/lib/ruby-lint/definitions/core/float.rb +307 -0
  78. data/lib/ruby-lint/definitions/core/float_domain_error.rb +8 -0
  79. data/lib/ruby-lint/definitions/core/gc.rb +57 -0
  80. data/lib/ruby-lint/definitions/core/gem.rb +3161 -0
  81. data/lib/ruby-lint/definitions/core/hash.rb +512 -0
  82. data/lib/ruby-lint/definitions/core/immediate_value.rb +19 -0
  83. data/lib/ruby-lint/definitions/core/index_error.rb +8 -0
  84. data/lib/ruby-lint/definitions/core/integer.rb +100 -0
  85. data/lib/ruby-lint/definitions/core/interrupt.rb +14 -0
  86. data/lib/ruby-lint/definitions/core/io.rb +928 -0
  87. data/lib/ruby-lint/definitions/core/ioerror.rb +8 -0
  88. data/lib/ruby-lint/definitions/core/kernel.rb +504 -0
  89. data/lib/ruby-lint/definitions/core/key_error.rb +8 -0
  90. data/lib/ruby-lint/definitions/core/load_error.rb +28 -0
  91. data/lib/ruby-lint/definitions/core/local_jump_error.rb +8 -0
  92. data/lib/ruby-lint/definitions/core/main.rb +25 -0
  93. data/lib/ruby-lint/definitions/core/marshal.rb +466 -0
  94. data/lib/ruby-lint/definitions/core/match_data.rb +73 -0
  95. data/lib/ruby-lint/definitions/core/math.rb +205 -0
  96. data/lib/ruby-lint/definitions/core/memory_segmention_error.rb +8 -0
  97. data/lib/ruby-lint/definitions/core/method.rb +61 -0
  98. data/lib/ruby-lint/definitions/core/module.rb +262 -0
  99. data/lib/ruby-lint/definitions/core/monitor.rb +39 -0
  100. data/lib/ruby-lint/definitions/core/monitor_mixin.rb +59 -0
  101. data/lib/ruby-lint/definitions/core/mutex.rb +32 -0
  102. data/lib/ruby-lint/definitions/core/name_error.rb +16 -0
  103. data/lib/ruby-lint/definitions/core/nil.rb +7 -0
  104. data/lib/ruby-lint/definitions/core/nil_class.rb +46 -0
  105. data/lib/ruby-lint/definitions/core/no_memory_error.rb +8 -0
  106. data/lib/ruby-lint/definitions/core/no_method_error.rb +18 -0
  107. data/lib/ruby-lint/definitions/core/not_implemented_error.rb +8 -0
  108. data/lib/ruby-lint/definitions/core/numeric.rb +123 -0
  109. data/lib/ruby-lint/definitions/core/object.rb +31 -0
  110. data/lib/ruby-lint/definitions/core/object_space.rb +41 -0
  111. data/lib/ruby-lint/definitions/core/open_struct.rb +49 -0
  112. data/lib/ruby-lint/definitions/core/option_parser.rb +1355 -0
  113. data/lib/ruby-lint/definitions/core/precision.rb +21 -0
  114. data/lib/ruby-lint/definitions/core/primitive_failure.rb +8 -0
  115. data/lib/ruby-lint/definitions/core/proc.rb +109 -0
  116. data/lib/ruby-lint/definitions/core/process.rb +602 -0
  117. data/lib/ruby-lint/definitions/core/psych.rb +2231 -0
  118. data/lib/ruby-lint/definitions/core/queue.rb +44 -0
  119. data/lib/ruby-lint/definitions/core/rake.rb +4784 -0
  120. data/lib/ruby-lint/definitions/core/rake_file_utils.rb +203 -0
  121. data/lib/ruby-lint/definitions/core/rakeversion.rb +7 -0
  122. data/lib/ruby-lint/definitions/core/random.rb +38 -0
  123. data/lib/ruby-lint/definitions/core/range.rb +104 -0
  124. data/lib/ruby-lint/definitions/core/range_error.rb +8 -0
  125. data/lib/ruby-lint/definitions/core/rational.rb +96 -0
  126. data/lib/ruby-lint/definitions/core/rb_config.rb +36 -0
  127. data/lib/ruby-lint/definitions/core/regexp.rb +396 -0
  128. data/lib/ruby-lint/definitions/core/regexp_error.rb +8 -0
  129. data/lib/ruby-lint/definitions/core/rubinius.rb +16637 -0
  130. data/lib/ruby-lint/definitions/core/ruby_copyright.rb +7 -0
  131. data/lib/ruby-lint/definitions/core/ruby_description.rb +7 -0
  132. data/lib/ruby-lint/definitions/core/ruby_engine.rb +7 -0
  133. data/lib/ruby-lint/definitions/core/ruby_lint.rb +93 -0
  134. data/lib/ruby-lint/definitions/core/ruby_patchlevel.rb +7 -0
  135. data/lib/ruby-lint/definitions/core/ruby_platform.rb +7 -0
  136. data/lib/ruby-lint/definitions/core/ruby_release_date.rb +7 -0
  137. data/lib/ruby-lint/definitions/core/ruby_version.rb +7 -0
  138. data/lib/ruby-lint/definitions/core/runtime_error.rb +8 -0
  139. data/lib/ruby-lint/definitions/core/scan_error.rb +8 -0
  140. data/lib/ruby-lint/definitions/core/script_error.rb +8 -0
  141. data/lib/ruby-lint/definitions/core/security_error.rb +8 -0
  142. data/lib/ruby-lint/definitions/core/shellwords.rb +37 -0
  143. data/lib/ruby-lint/definitions/core/signal.rb +37 -0
  144. data/lib/ruby-lint/definitions/core/signal_exception.rb +19 -0
  145. data/lib/ruby-lint/definitions/core/singleton.rb +37 -0
  146. data/lib/ruby-lint/definitions/core/sized_queue.rb +42 -0
  147. data/lib/ruby-lint/definitions/core/standard_error.rb +8 -0
  148. data/lib/ruby-lint/definitions/core/stderr.rb +7 -0
  149. data/lib/ruby-lint/definitions/core/stdin.rb +7 -0
  150. data/lib/ruby-lint/definitions/core/stdout.rb +7 -0
  151. data/lib/ruby-lint/definitions/core/stop_iteration.rb +8 -0
  152. data/lib/ruby-lint/definitions/core/string.rb +713 -0
  153. data/lib/ruby-lint/definitions/core/string_io.rb +287 -0
  154. data/lib/ruby-lint/definitions/core/string_scanner.rb +158 -0
  155. data/lib/ruby-lint/definitions/core/struct.rb +357 -0
  156. data/lib/ruby-lint/definitions/core/syck.rb +30 -0
  157. data/lib/ruby-lint/definitions/core/symbol.rb +90 -0
  158. data/lib/ruby-lint/definitions/core/syntax_error.rb +44 -0
  159. data/lib/ruby-lint/definitions/core/system_call_error.rb +31 -0
  160. data/lib/ruby-lint/definitions/core/system_exit.rb +19 -0
  161. data/lib/ruby-lint/definitions/core/system_stack_error.rb +8 -0
  162. data/lib/ruby-lint/definitions/core/thread.rb +209 -0
  163. data/lib/ruby-lint/definitions/core/thread_error.rb +8 -0
  164. data/lib/ruby-lint/definitions/core/thread_group.rb +22 -0
  165. data/lib/ruby-lint/definitions/core/time.rb +233 -0
  166. data/lib/ruby-lint/definitions/core/toplevel_binding.rb +7 -0
  167. data/lib/ruby-lint/definitions/core/true.rb +7 -0
  168. data/lib/ruby-lint/definitions/core/true_class.rb +30 -0
  169. data/lib/ruby-lint/definitions/core/type_error.rb +8 -0
  170. data/lib/ruby-lint/definitions/core/unbound_method.rb +51 -0
  171. data/lib/ruby-lint/definitions/core/unmarshalable.rb +13 -0
  172. data/lib/ruby-lint/definitions/core/unsupported_library_error.rb +8 -0
  173. data/lib/ruby-lint/definitions/core/weak_ref.rb +42 -0
  174. data/lib/ruby-lint/definitions/core/zero_division_error.rb +8 -0
  175. data/lib/ruby-lint/definitions_builder.rb +692 -0
  176. data/lib/ruby-lint/extensions/string.rb +15 -0
  177. data/lib/ruby-lint/helper/constant_paths.rb +41 -0
  178. data/lib/ruby-lint/helper/conversion.rb +33 -0
  179. data/lib/ruby-lint/helper/current_scope.rb +98 -0
  180. data/lib/ruby-lint/helper/methods.rb +91 -0
  181. data/lib/ruby-lint/inspector.rb +191 -0
  182. data/lib/ruby-lint/iterator.rb +187 -127
  183. data/lib/ruby-lint/node.rb +107 -0
  184. data/lib/ruby-lint/parser.rb +510 -1137
  185. data/lib/ruby-lint/parser_error.rb +15 -27
  186. data/lib/ruby-lint/presenter/json.rb +19 -0
  187. data/lib/ruby-lint/presenter/text.rb +37 -0
  188. data/lib/ruby-lint/report.rb +95 -53
  189. data/lib/ruby-lint/report/entry.rb +71 -0
  190. data/lib/ruby-lint/template/definition.erb +24 -0
  191. data/lib/ruby-lint/template/scope.rb +25 -0
  192. data/lib/ruby-lint/variable_predicates.rb +109 -0
  193. data/lib/ruby-lint/version.rb +1 -1
  194. data/ruby-lint.gemspec +19 -8
  195. data/spec/helper.rb +10 -2
  196. data/spec/ruby-lint/analyze/argument_amount.rb +91 -0
  197. data/spec/ruby-lint/analyze/shadowing_variables.rb +69 -14
  198. data/spec/ruby-lint/analyze/undefined_methods.rb +174 -0
  199. data/spec/ruby-lint/analyze/undefined_variables.rb +70 -179
  200. data/spec/ruby-lint/analyze/unused_variables.rb +63 -183
  201. data/spec/ruby-lint/configuration.rb +15 -0
  202. data/spec/ruby-lint/constant_loader.rb +32 -0
  203. data/spec/ruby-lint/definition/dsl.rb +142 -0
  204. data/spec/ruby-lint/definition/method_calls.rb +26 -0
  205. data/spec/ruby-lint/definition/ruby_method.rb +175 -0
  206. data/spec/ruby-lint/definition/ruby_object.rb +228 -0
  207. data/spec/ruby-lint/definitions_builder/assignments/arrays.rb +71 -0
  208. data/spec/ruby-lint/definitions_builder/assignments/hashes.rb +65 -0
  209. data/spec/ruby-lint/definitions_builder/assignments/objects.rb +23 -0
  210. data/spec/ruby-lint/definitions_builder/assignments/optional.rb +22 -0
  211. data/spec/ruby-lint/definitions_builder/assignments/return_values.rb +78 -0
  212. data/spec/ruby-lint/definitions_builder/assignments/variables.rb +71 -0
  213. data/spec/ruby-lint/definitions_builder/associate_nodes.rb +17 -0
  214. data/spec/ruby-lint/definitions_builder/blocks.rb +40 -0
  215. data/spec/ruby-lint/definitions_builder/classes.rb +230 -0
  216. data/spec/ruby-lint/definitions_builder/for.rb +16 -0
  217. data/spec/ruby-lint/definitions_builder/methods.rb +147 -0
  218. data/spec/ruby-lint/definitions_builder/modules.rb +175 -0
  219. data/spec/ruby-lint/definitions_builder/reference_amount.rb +31 -0
  220. data/spec/ruby-lint/definitions_builder/unused.rb +15 -0
  221. data/spec/ruby-lint/extensions/string.rb +7 -0
  222. data/spec/ruby-lint/iterator.rb +42 -417
  223. data/spec/ruby-lint/node.rb +38 -0
  224. data/spec/ruby-lint/parser/assignments.rb +225 -0
  225. data/spec/ruby-lint/parser/classes.rb +80 -122
  226. data/spec/ruby-lint/parser/errors.rb +7 -14
  227. data/spec/ruby-lint/parser/metadata.rb +17 -0
  228. data/spec/ruby-lint/parser/method_definitions.rb +111 -0
  229. data/spec/ruby-lint/parser/methods.rb +184 -216
  230. data/spec/ruby-lint/parser/modules.rb +54 -33
  231. data/spec/ruby-lint/parser/operators.rb +30 -65
  232. data/spec/ruby-lint/parser/statements/begin.rb +55 -0
  233. data/spec/ruby-lint/parser/statements/case.rb +34 -0
  234. data/spec/ruby-lint/parser/statements/defined.rb +11 -0
  235. data/spec/ruby-lint/parser/statements/for.rb +34 -0
  236. data/spec/ruby-lint/parser/statements/if.rb +46 -0
  237. data/spec/ruby-lint/parser/statements/return.rb +14 -0
  238. data/spec/ruby-lint/parser/statements/super.rb +49 -0
  239. data/spec/ruby-lint/parser/statements/unless.rb +42 -0
  240. data/spec/ruby-lint/parser/statements/until.rb +25 -0
  241. data/spec/ruby-lint/parser/statements/while.rb +25 -0
  242. data/spec/ruby-lint/parser/statements/yield.rb +18 -0
  243. data/spec/ruby-lint/parser/types/arrays.rb +47 -0
  244. data/spec/ruby-lint/parser/types/booleans.rb +11 -0
  245. data/spec/ruby-lint/parser/types/constants.rb +32 -0
  246. data/spec/ruby-lint/parser/types/hashes.rb +55 -0
  247. data/spec/ruby-lint/parser/types/nil.rb +7 -0
  248. data/spec/ruby-lint/parser/types/numbers.rb +11 -0
  249. data/spec/ruby-lint/parser/types/procs.rb +11 -0
  250. data/spec/ruby-lint/parser/types/ranges.rb +11 -0
  251. data/spec/ruby-lint/parser/types/regexp.rb +27 -0
  252. data/spec/ruby-lint/parser/types/strings.rb +44 -0
  253. data/spec/ruby-lint/parser/types/symbols.rb +15 -0
  254. data/spec/ruby-lint/presenter/json.rb +31 -0
  255. data/spec/ruby-lint/presenter/text.rb +22 -0
  256. data/spec/ruby-lint/report.rb +45 -15
  257. data/spec/ruby-lint/report/entry.rb +24 -0
  258. data/spec/support/bacon.rb +33 -0
  259. data/spec/support/building.rb +43 -0
  260. data/spec/support/definitions.rb +23 -0
  261. data/spec/support/parsing.rb +23 -0
  262. data/spec/support/simplecov.rb +16 -0
  263. data/task/build.rake +9 -0
  264. data/task/checksum.rake +13 -0
  265. data/task/coverage.rake +6 -0
  266. data/task/doc.rake +5 -0
  267. data/task/generate.rake +34 -0
  268. data/task/graphviz.rake +12 -0
  269. data/task/stdlib.rake +2 -9
  270. data/task/tag.rake +6 -0
  271. metadata +337 -68
  272. metadata.gz.asc +17 -0
  273. data/.rbenv-version +0 -1
  274. data/lib/ruby-lint/analyze/coding_style.rb +0 -407
  275. data/lib/ruby-lint/analyze/definitions.rb +0 -244
  276. data/lib/ruby-lint/analyze/method_validation.rb +0 -104
  277. data/lib/ruby-lint/callback.rb +0 -67
  278. data/lib/ruby-lint/constant_importer.rb +0 -112
  279. data/lib/ruby-lint/definition.rb +0 -230
  280. data/lib/ruby-lint/formatter/text.rb +0 -54
  281. data/lib/ruby-lint/helper/definition_resolver.rb +0 -143
  282. data/lib/ruby-lint/helper/scoping.rb +0 -138
  283. data/lib/ruby-lint/options.rb +0 -58
  284. data/lib/ruby-lint/token/assignment_token.rb +0 -35
  285. data/lib/ruby-lint/token/begin_rescue_token.rb +0 -57
  286. data/lib/ruby-lint/token/block_token.rb +0 -26
  287. data/lib/ruby-lint/token/case_token.rb +0 -44
  288. data/lib/ruby-lint/token/class_token.rb +0 -24
  289. data/lib/ruby-lint/token/keyword_token.rb +0 -43
  290. data/lib/ruby-lint/token/method_definition_token.rb +0 -64
  291. data/lib/ruby-lint/token/method_token.rb +0 -56
  292. data/lib/ruby-lint/token/parameters_token.rb +0 -99
  293. data/lib/ruby-lint/token/regexp_token.rb +0 -15
  294. data/lib/ruby-lint/token/statement_token.rb +0 -69
  295. data/lib/ruby-lint/token/token.rb +0 -176
  296. data/lib/ruby-lint/token/variable_token.rb +0 -18
  297. data/spec/benchmarks/memory.rb +0 -52
  298. data/spec/benchmarks/parse_parser.rb +0 -16
  299. data/spec/fixtures/stdlib/un.rb +0 -348
  300. data/spec/ruby-lint/analyze/coding_style.rb +0 -224
  301. data/spec/ruby-lint/analyze/complex/un.rb +0 -29
  302. data/spec/ruby-lint/analyze/definitions/classes.rb +0 -114
  303. data/spec/ruby-lint/analyze/definitions/methods.rb +0 -91
  304. data/spec/ruby-lint/analyze/definitions/modules.rb +0 -207
  305. data/spec/ruby-lint/analyze/definitions/variables.rb +0 -103
  306. data/spec/ruby-lint/analyze/method_validation.rb +0 -177
  307. data/spec/ruby-lint/callback.rb +0 -28
  308. data/spec/ruby-lint/constant_importer.rb +0 -27
  309. data/spec/ruby-lint/definition.rb +0 -96
  310. data/spec/ruby-lint/formatter/text.rb +0 -21
  311. data/spec/ruby-lint/parser/arrays.rb +0 -147
  312. data/spec/ruby-lint/parser/expander_assignments.rb +0 -183
  313. data/spec/ruby-lint/parser/hashes.rb +0 -136
  314. data/spec/ruby-lint/parser/keywords.rb +0 -89
  315. data/spec/ruby-lint/parser/objects.rb +0 -39
  316. data/spec/ruby-lint/parser/procs.rb +0 -113
  317. data/spec/ruby-lint/parser/ranges.rb +0 -49
  318. data/spec/ruby-lint/parser/regexp.rb +0 -31
  319. data/spec/ruby-lint/parser/scalars.rb +0 -93
  320. data/spec/ruby-lint/parser/statements.rb +0 -591
  321. data/spec/ruby-lint/parser/variables.rb +0 -230
@@ -1,193 +1,253 @@
1
1
  module RubyLint
2
2
  ##
3
- # {RubyLint::Iterator} is a class that can be used to iterate over the AST
4
- # generated by {RubyLint::Parser} and execute callback methods for each
5
- # encountered node. Basic usage is as following:
3
+ # The Iterator class provides the means to iterate over an AST generated by
4
+ # {RubyLint::Parser} using callback methods for the various node types
5
+ # generated by this parser.
6
6
  #
7
- # code = <<-CODE
8
- # [10, 20].each do |number|
9
- # puts number
10
- # end
11
- # CODE
12
- #
13
- # parser = RubyLint::Parser.new(code)
14
- # tokens = parser.parse
15
- # iterator = RubyLint::Iterator.new
16
- #
17
- # iterator.run(tokens)
7
+ # For each node type two events are called: one before and one after
8
+ # processing the node and all of its children. The names of these events are
9
+ # the following:
18
10
  #
19
- # This particular example doesn't do anything but iterating over the nodes
20
- # due to no callback classes being defined. How to add these classes is
21
- # discussed below.
11
+ # * `on_X`
12
+ # * `after_X`
22
13
  #
23
- # ## Callback Classes
14
+ # Here "X" is the name of the event. For example, when iterator an integer
15
+ # this would result in the event names `on_integer` and `after_integer`.
24
16
  #
25
- # Without any custom callback classes the iterator class is fairly useless as
26
- # it does nothing but iterate over all the nodes. These classes are defined
27
- # as any ordinary class and are added to an interator instance using
28
- # {RubyLint::Iterator#bind}. At the most basic level each callback class should
29
- # have the following structure:
17
+ # These event names are used to call the corresponding callback methods if
18
+ # they exist. Each callback method takes a single argument: the node (an
19
+ # instance of {RubyLint::Node}) that belongs to the event.
30
20
  #
31
- # class MyCallback
32
- # attr_reader :options
21
+ # Creating iterator classes is done by extending this particular class and
22
+ # adding the needed methods to it:
33
23
  #
34
- # def initialize(report = nil, storage = {})
35
- # @report = report
36
- # @storage = storage
24
+ # class MyIterator < RubyLint::Iterator
25
+ # def on_integer(node)
26
+ # puts node.children[0]
37
27
  # end
38
- # end
39
- #
40
- # The constructor method should take two parameters: the first one is used
41
- # for storing a instance of {RubyLint::Report} (this parameter should be set to
42
- # `nil` by default). The second parameter is a Hash containing custom data
43
- # that is shared between callback classes bound to the same {RubyLint::Iterator}
44
- # instance. This Hash can be used to share, for example, definitions defined
45
- # in callback class #1 with callback class #2.
46
- #
47
- # To make this, as well as adding errors and such to a report easier your own
48
- # classes can extend {RubyLint::Callback}:
49
- #
50
- # class MyCallback < RubyLint::Callback
51
28
  #
29
+ # def after_integer(node)
30
+ # puts '---'
31
+ # end
52
32
  # end
53
33
  #
54
- # To add your class to an iterator instance you'd run the following:
55
- #
56
- # iterator = RubyLint::Iterator.new
34
+ # When used this particular iterator class would display the values of all
35
+ # integers it processes. After processing an integer it will display three
36
+ # dashes.
57
37
  #
58
- # iterator.bind(MyCallback)
38
+ # Each instance of a class that subclasses {RubyLint::Iterator} also has
39
+ # access to the instance variable `@options`. This instance variable is used
40
+ # to store certain information, such as the list of definitions for a block
41
+ # of Ruby code. The following two keys are set by default:
59
42
  #
60
- # ## Callback Methods
43
+ # * `:definitions`: a set of Ruby definitions such as classes and methods.
44
+ # * `:report`: an instance of {RubyLint::Report} that can be used for adding
45
+ # information about the analyzed code.
46
+ # * `:node_definitions`: a Hash that associates {RubyLint::Node} instances
47
+ # with the corresponding scope.
61
48
  #
62
- # When iterating over an AST the method {RubyLint::Iterator#iterator} calls two
63
- # callback methods based on the event name stored in the token (in
64
- # {RubyLint::Token::Token#event}):
49
+ # To make it easier to add data to a report sub classes can use the following
50
+ # three methods:
65
51
  #
66
- # * `on_EVENT_NAME`
67
- # * `after_EVENT_NAME`
52
+ # * error
53
+ # * info
54
+ # * warning
68
55
  #
69
- # Where `EVENT_NAME` is the name of the event. For example, for strings this
70
- # would result in the following methods being called:
71
- #
72
- # * `on_string`
73
- # * `after_string`
74
- #
75
- # Note that the "after" callback is not executed until all child nodes have
76
- # been processed.
77
- #
78
- # Each method should take a single parameter that contains details about the
79
- # token that is currently being processed. Each token is an instance of
80
- # {RubyLint::Token::Token} or one of its child classes.
81
- #
82
- # If you wanted to display the values of all strings in your console you'd
83
- # write the following class:
84
- #
85
- # class StringPrinter < RubyLint::Callback
86
- # def on_string(token)
87
- # puts token.value
88
- # end
89
- # end
56
+ # These methods take away some of the boilerplate that would otherwise be
57
+ # required to check for a report and add data to it if it's set.
90
58
  #
91
59
  class Iterator
92
60
  ##
93
- # Array containing a set of instance specific callback objects.
61
+ # Hash containing the options that were set for the iterator.
94
62
  #
95
- # @return [Array]
63
+ # @return [Hash]
96
64
  #
97
- attr_reader :callbacks
65
+ attr_reader :options
98
66
 
99
67
  ##
100
- # Returns the Hash that is used by callback classes to store arbitrary
101
- # data.
68
+ # @param [Hash] options Hash containing custom options to set for the
69
+ # iterator.
102
70
  #
103
- # @return [Hash]
71
+ def initialize(options = {})
72
+ @options = default_options.merge(options)
73
+ @definitions = []
74
+ @call_types = []
75
+ end
76
+
77
+ ##
78
+ # Recursively processes the specified list of nodes.
104
79
  #
105
- attr_reader :storage
80
+ # @param [RubyLint::Node] node A node and optionally a set of sub nodes to
81
+ # iterate over.
82
+ #
83
+ def iterate(node)
84
+ return unless node.is_a?(Node)
85
+
86
+ before, after = callback_names(node)
87
+
88
+ execute_callback(before, node)
89
+
90
+ node.children.each do |child|
91
+ if child.is_a?(Array)
92
+ child.each { |c| iterate(c) }
93
+ else
94
+ iterate(child)
95
+ end
96
+ end
97
+
98
+ execute_callback(after, node)
99
+ end
100
+
101
+ protected
106
102
 
107
103
  ##
108
- # Creates a new instance of the iterator class.
104
+ # Adds an error message to the report.
109
105
  #
110
- # @param [RubyLint::Report|NilClass] report The report to use, set to `nil` by
111
- # default.
106
+ # @param [String] message The message to add.
107
+ # @param [RubyLint::Node] node The node for which to add the message.
112
108
  #
113
- def initialize(report = nil)
114
- @callbacks = []
115
- @report = report
116
- @storage = {}
109
+ def error(message, node)
110
+ add_message(:error, message, node)
117
111
  end
118
112
 
119
113
  ##
120
- # Processes the entire AST for each callback class in sequence. For each
121
- # callback class the method {RubyLint::Iterator#iterate} is called to process
122
- # an *entire* AST before moving on to the next callback class.
114
+ # Adds a warning message to the report.
123
115
  #
124
- # @param [#each] nodes An array of nodes to process.
116
+ # @see RubyLint::Callback#error
125
117
  #
126
- def run(nodes)
127
- @callbacks.each do |obj|
128
- execute_callback(obj, :on_start)
118
+ def warning(message, node)
119
+ add_message(:warning, message, node)
120
+ end
129
121
 
130
- iterate(obj, nodes)
122
+ ##
123
+ # Adds a regular informational message to the report.
124
+ #
125
+ # @see RubyLint::Callback#error
126
+ #
127
+ def info(message, node)
128
+ add_message(:info, message, node)
129
+ end
131
130
 
132
- execute_callback(obj, :on_finish)
131
+ ##
132
+ # Adds a message of the given level.
133
+ #
134
+ # @param [Symbol] level
135
+ # @param [String] message
136
+ # @param [String] node
137
+ #
138
+ def add_message(level, message, node)
139
+ if has_report?
140
+ @options[:report].add(
141
+ level,
142
+ message,
143
+ node.line,
144
+ node.column,
145
+ node.file
146
+ )
133
147
  end
134
148
  end
135
149
 
136
150
  ##
137
- # Processes an AST and calls callbacks methods for a specific callback
138
- # object.
151
+ # Returns `true` if the current iterator has a report instance set.
139
152
  #
140
- # @param [RubyLint::Callback] callback_obj The callback object on which to
141
- # invoke callback method.
142
- # @param [#each] nodes An array (or a different object that responds to
143
- # `#each()`) that contains a set of tokens to process.
153
+ # @return [TrueClass|FalseClass]
144
154
  #
145
- def iterate(callback_obj, nodes)
146
- nodes.each do |node|
147
- next unless node.is_a?(RubyLint::Token::Token)
148
-
149
- event_name = node.event.to_s
150
- callback_name = 'on_' + event_name
151
- after_callback = 'after_' + event_name
155
+ def has_report?
156
+ return @options[:report].is_a?(Report)
157
+ end
152
158
 
153
- execute_callback(callback_obj, callback_name, node)
159
+ ##
160
+ # Returns a definition list to use for the last segment in the constant
161
+ # path. If one of the segments is invalid `nil` is returned instead.
162
+ #
163
+ # @param [Array] path An array of nodes or definitions that make up the
164
+ # constant path.
165
+ # @return [RubyLint::Definition::RubyObject|NilClass]
166
+ #
167
+ def resolve_definitions(path)
168
+ current = definitions
154
169
 
155
- node.child_nodes.each do |child_nodes|
156
- iterate(callback_obj, child_nodes) if child_nodes.respond_to?(:each)
170
+ path.each do |segment|
171
+ if segment.is_a?(Definition::RubyObject)
172
+ name = segment.name
173
+ else
174
+ name = segment.children[0]
157
175
  end
158
176
 
159
- execute_callback(callback_obj, after_callback, node)
177
+ found = current.lookup(segment.type, name)
178
+ found ? current = found : return
160
179
  end
180
+
181
+ return current
161
182
  end
162
183
 
163
184
  ##
164
- # Adds the specified class to the list of callback classes for this
165
- # instance.
185
+ # Returns the call type to use for method calls.
166
186
  #
167
- # @example
168
- # iterator = RubyLint::Iterator.new
187
+ # @return [Symbol]
169
188
  #
170
- # iterator.bind(CustomCallbackClass)
189
+ def call_type
190
+ return @call_types.empty? ? :instance_method : @call_types[-1]
191
+ end
192
+
193
+ ##
194
+ # Returns the current definition list to use.
171
195
  #
172
- # @param [Class] callback_class The class to add.
196
+ # @return [RubyLint::Definition::RubyObject]
173
197
  #
174
- def bind(callback_class)
175
- @callbacks << callback_class.new(@report, @storage)
198
+ def definitions
199
+ return @definitions.empty? ? @options[:definitions] : @definitions[-1]
176
200
  end
177
201
 
178
- private
202
+ protected
179
203
 
180
204
  ##
181
- # Loops through all the bound callback classes and executes the specified
182
- # callback method if it exists.
205
+ # Executes the specified callback method if it exists.
183
206
  #
184
- # @param [RubyLint::Callback] obj The object on which to invoke the callback
185
- # method.
186
207
  # @param [String|Symbol] name The name of the callback method to execute.
187
208
  # @param [Array] args Arguments to pass to the callback method.
188
209
  #
189
- def execute_callback(obj, name, *args)
190
- obj.send(name, *args) if obj.respond_to?(name)
210
+ def execute_callback(name, *args)
211
+ send(name, *args) if respond_to?(name)
212
+ end
213
+
214
+ ##
215
+ # Returns an array containin the callback names for the specified node.
216
+ #
217
+ # @param [RubyLint::Node] node
218
+ # @return [Array]
219
+ #
220
+ def callback_names(node)
221
+ return [:"on_#{node.type}", :"after_#{node.type}"]
222
+ end
223
+
224
+ ##
225
+ # Associates a definitions object with a node of the AST.
226
+ #
227
+ # @param [RubyLint::Node] node
228
+ # @param [RubyLint::Definition::RubyObject] definitions
229
+ #
230
+ def associate_node_definition(node, definitions)
231
+ @options[:node_definitions][node] = definitions
232
+ end
233
+
234
+ ##
235
+ # Retrieves the definitions list associated to an AST node.
236
+ #
237
+ # @param [RubyLint::Node] node
238
+ # @return [RubyLint::Definition::RubyObject|NilClass]
239
+ #
240
+ def associated_definition(node)
241
+ return @options[:node_definitions][node]
242
+ end
243
+
244
+ ##
245
+ # Returns a Hash containing the default configuration options.
246
+ #
247
+ # @return [Hash]
248
+ #
249
+ def default_options
250
+ return {:node_definitions => {}}
191
251
  end
192
252
  end # Iterator
193
253
  end # RubyLint
@@ -0,0 +1,107 @@
1
+ module RubyLint
2
+ ##
3
+ # {RubyLint::Node} is a class that represents a single node in the AST of a
4
+ # Ruby program. It contains information such as the type, children, line
5
+ # number and column number.
6
+ #
7
+ class Node < AST::Node
8
+ include VariablePredicates
9
+
10
+ ##
11
+ # Returns the line number of the node.
12
+ #
13
+ # @return [Fixnum]
14
+ #
15
+ attr_reader :line
16
+
17
+ ##
18
+ # Returns the column number of the node.
19
+ #
20
+ # @return [Fixnum]
21
+ #
22
+ attr_reader :column
23
+
24
+ ##
25
+ # Returns the name of the file that the node belongs to.
26
+ #
27
+ # @return [String]
28
+ #
29
+ attr_reader :file
30
+
31
+ ##
32
+ # @return [String]
33
+ #
34
+ def name
35
+ name = children[0] || type
36
+ name = name.is_a?(Node) ? name.children[0] : name
37
+
38
+ return name.to_s
39
+ end
40
+
41
+ ##
42
+ # @return [Mixed]
43
+ #
44
+ def value
45
+ value = collection? ? children : children[-1]
46
+ value = children[1] if variable?
47
+
48
+ return value
49
+ end
50
+
51
+ ##
52
+ # Returns the receiver of the method call/definition.
53
+ #
54
+ # @return [RubyLint::Node]
55
+ #
56
+ def receiver
57
+ return method? ? children[-1] : children[-2]
58
+ end
59
+
60
+ ##
61
+ # Returns a symbol that indicates if a node is either a method or instance
62
+ # method.
63
+ #
64
+ # @return [Symbol]
65
+ #
66
+ def method_type
67
+ return receiver ? :method : :instance_method
68
+ end
69
+
70
+ ##
71
+ # Gathers a set of arguments and returns them as an Array.
72
+ #
73
+ # @param [#to_sym] type The type of arguments to gather.
74
+ # @return [Array]
75
+ #
76
+ def gather_arguments(type = :argument)
77
+ args = []
78
+ type = type.to_sym
79
+
80
+ children.each do |child|
81
+ if !child.is_a?(Node) or child.type != :arguments
82
+ next
83
+ end
84
+
85
+ child.children.each do |child_arg|
86
+ next unless child_arg.type == type
87
+
88
+ args << child_arg.children[0]
89
+ end
90
+ end
91
+
92
+ return args
93
+ end
94
+
95
+ ##
96
+ # Iterates over each argument of the given type.
97
+ #
98
+ # @param [Symbol] type The argument type.
99
+ # @yieldparam [RubyLint::Node] argument
100
+ #
101
+ def each_argument(type = :argument)
102
+ gather_arguments(type).each do |arg|
103
+ yield arg
104
+ end
105
+ end
106
+ end # Node
107
+ end # RubyLint