ruby-lint 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (347) hide show
  1. data.tar.gz.asc +14 -14
  2. data/.gitignore +1 -2
  3. data/.rubocop.yml +59 -0
  4. data/.travis.yml +3 -7
  5. data/.yardopts +2 -2
  6. data/Gemfile +4 -0
  7. data/MANIFEST +103 -67
  8. data/README.md +13 -31
  9. data/Rakefile +1 -6
  10. data/checksum/ruby-lint-0.0.3.gem.sha512 +1 -0
  11. data/debug/memory_usage.rb +14 -0
  12. data/debug/profile.rb +18 -0
  13. data/doc/architecture.md +14 -18
  14. data/doc/changelog.md +29 -0
  15. data/doc/code_analysis.md +12 -12
  16. data/doc/configuration.md +21 -50
  17. data/doc/graphviz/flow.dot +1 -1
  18. data/doc/images/flow.png +0 -0
  19. data/lib/ruby-lint.rb +33 -19
  20. data/lib/ruby-lint/analysis/argument_amount.rb +84 -0
  21. data/lib/ruby-lint/analysis/base.rb +132 -0
  22. data/lib/ruby-lint/analysis/confusing_variables.rb +26 -0
  23. data/lib/ruby-lint/analysis/pedantics.rb +36 -0
  24. data/lib/ruby-lint/analysis/shadowing_variables.rb +47 -0
  25. data/lib/ruby-lint/analysis/undefined_methods.rb +91 -0
  26. data/lib/ruby-lint/analysis/undefined_variables.rb +46 -0
  27. data/lib/ruby-lint/analysis/unused_variables.rb +49 -0
  28. data/lib/ruby-lint/ast/builder.rb +17 -0
  29. data/lib/ruby-lint/ast/node.rb +39 -0
  30. data/lib/ruby-lint/cli.rb +0 -19
  31. data/lib/ruby-lint/cli/analyze.rb +54 -28
  32. data/lib/ruby-lint/cli/ast.rb +21 -6
  33. data/lib/ruby-lint/cli/base.rb +0 -23
  34. data/lib/ruby-lint/configuration.rb +112 -42
  35. data/lib/ruby-lint/constant_loader.rb +10 -28
  36. data/lib/ruby-lint/default_names.rb +19 -0
  37. data/lib/ruby-lint/definition/constant_proxy.rb +56 -0
  38. data/lib/ruby-lint/definition/ruby_method.rb +21 -143
  39. data/lib/ruby-lint/definition/ruby_object.rb +142 -246
  40. data/lib/ruby-lint/definition_builder/base.rb +43 -0
  41. data/lib/ruby-lint/definition_builder/primitive.rb +39 -0
  42. data/lib/ruby-lint/definition_builder/ruby_array.rb +77 -0
  43. data/lib/ruby-lint/definition_builder/ruby_block.rb +34 -0
  44. data/lib/ruby-lint/definition_builder/ruby_class.rb +24 -0
  45. data/lib/ruby-lint/definition_builder/ruby_hash.rb +37 -0
  46. data/lib/ruby-lint/definition_builder/ruby_method.rb +84 -0
  47. data/lib/ruby-lint/definition_builder/ruby_module.rb +68 -0
  48. data/lib/ruby-lint/definition_generator.rb +41 -15
  49. data/lib/ruby-lint/definitions/core/arg0.rb +1 -1
  50. data/lib/ruby-lint/definitions/core/argf.rb +1 -1
  51. data/lib/ruby-lint/definitions/core/argument_error.rb +2 -2
  52. data/lib/ruby-lint/definitions/core/argv.rb +1 -1
  53. data/lib/ruby-lint/definitions/core/array.rb +6 -6
  54. data/lib/ruby-lint/definitions/core/autoload.rb +2 -2
  55. data/lib/ruby-lint/definitions/core/basic_object.rb +3 -3
  56. data/lib/ruby-lint/definitions/core/bignum.rb +2 -2
  57. data/lib/ruby-lint/definitions/core/binding.rb +2 -2
  58. data/lib/ruby-lint/definitions/core/class.rb +2 -2
  59. data/lib/ruby-lint/definitions/core/comparable.rb +1 -1
  60. data/lib/ruby-lint/definitions/core/complex.rb +4 -4
  61. data/lib/ruby-lint/definitions/core/condition_variable.rb +2 -2
  62. data/lib/ruby-lint/definitions/core/continuation.rb +2 -2
  63. data/lib/ruby-lint/definitions/core/data.rb +2 -2
  64. data/lib/ruby-lint/definitions/core/date.rb +34 -34
  65. data/lib/ruby-lint/definitions/core/date_time.rb +26 -26
  66. data/lib/ruby-lint/definitions/core/default_record_separator.rb +1 -1
  67. data/lib/ruby-lint/definitions/core/digest.rb +14 -14
  68. data/lib/ruby-lint/definitions/core/dir.rb +34 -34
  69. data/lib/ruby-lint/definitions/core/encoding.rb +237 -237
  70. data/lib/ruby-lint/definitions/core/encoding_error.rb +2 -2
  71. data/lib/ruby-lint/definitions/core/enumerable.rb +15 -15
  72. data/lib/ruby-lint/definitions/core/enumerator.rb +2 -2
  73. data/lib/ruby-lint/definitions/core/env.rb +1 -1
  74. data/lib/ruby-lint/definitions/core/eoferror.rb +2 -2
  75. data/lib/ruby-lint/definitions/core/erb.rb +22 -22
  76. data/lib/ruby-lint/definitions/core/errno.rb +525 -525
  77. data/lib/ruby-lint/definitions/core/etc.rb +6 -6
  78. data/lib/ruby-lint/definitions/core/exception.rb +2 -2
  79. data/lib/ruby-lint/definitions/core/false.rb +1 -1
  80. data/lib/ruby-lint/definitions/core/false_class.rb +2 -2
  81. data/lib/ruby-lint/definitions/core/fatal_error.rb +2 -2
  82. data/lib/ruby-lint/definitions/core/fiber.rb +2 -2
  83. data/lib/ruby-lint/definitions/core/fiber_error.rb +2 -2
  84. data/lib/ruby-lint/definitions/core/file.rb +68 -68
  85. data/lib/ruby-lint/definitions/core/file_list.rb +2 -2
  86. data/lib/ruby-lint/definitions/core/file_test.rb +1 -1
  87. data/lib/ruby-lint/definitions/core/file_utils.rb +16 -16
  88. data/lib/ruby-lint/definitions/core/fixnum.rb +4 -4
  89. data/lib/ruby-lint/definitions/core/float.rb +16 -16
  90. data/lib/ruby-lint/definitions/core/float_domain_error.rb +2 -2
  91. data/lib/ruby-lint/definitions/core/gc.rb +2 -2
  92. data/lib/ruby-lint/definitions/core/gem.rb +119 -119
  93. data/lib/ruby-lint/definitions/core/hash.rb +14 -14
  94. data/lib/ruby-lint/definitions/core/immediate_value.rb +1 -1
  95. data/lib/ruby-lint/definitions/core/index_error.rb +2 -2
  96. data/lib/ruby-lint/definitions/core/integer.rb +2 -2
  97. data/lib/ruby-lint/definitions/core/interrupt.rb +2 -2
  98. data/lib/ruby-lint/definitions/core/io.rb +38 -38
  99. data/lib/ruby-lint/definitions/core/ioerror.rb +2 -2
  100. data/lib/ruby-lint/definitions/core/kernel.rb +3 -3
  101. data/lib/ruby-lint/definitions/core/key_error.rb +2 -2
  102. data/lib/ruby-lint/definitions/core/load_error.rb +6 -6
  103. data/lib/ruby-lint/definitions/core/local_jump_error.rb +2 -2
  104. data/lib/ruby-lint/definitions/core/main.rb +1 -1
  105. data/lib/ruby-lint/definitions/core/marshal.rb +35 -35
  106. data/lib/ruby-lint/definitions/core/match_data.rb +2 -2
  107. data/lib/ruby-lint/definitions/core/math.rb +7 -7
  108. data/lib/ruby-lint/definitions/core/memory_segmention_error.rb +2 -2
  109. data/lib/ruby-lint/definitions/core/method.rb +2 -2
  110. data/lib/ruby-lint/definitions/core/module.rb +1 -1
  111. data/lib/ruby-lint/definitions/core/monitor.rb +4 -4
  112. data/lib/ruby-lint/definitions/core/monitor_mixin.rb +5 -5
  113. data/lib/ruby-lint/definitions/core/mutex.rb +2 -2
  114. data/lib/ruby-lint/definitions/core/name_error.rb +2 -2
  115. data/lib/ruby-lint/definitions/core/nil.rb +1 -1
  116. data/lib/ruby-lint/definitions/core/nil_class.rb +2 -2
  117. data/lib/ruby-lint/definitions/core/no_memory_error.rb +2 -2
  118. data/lib/ruby-lint/definitions/core/no_method_error.rb +2 -2
  119. data/lib/ruby-lint/definitions/core/not_implemented_error.rb +2 -2
  120. data/lib/ruby-lint/definitions/core/numeric.rb +2 -2
  121. data/lib/ruby-lint/definitions/core/object.rb +2 -2
  122. data/lib/ruby-lint/definitions/core/object_space.rb +1 -1
  123. data/lib/ruby-lint/definitions/core/open_struct.rb +3 -3
  124. data/lib/ruby-lint/definitions/core/option_parser.rb +83 -83
  125. data/lib/ruby-lint/definitions/core/precision.rb +1 -1
  126. data/lib/ruby-lint/definitions/core/primitive_failure.rb +2 -2
  127. data/lib/ruby-lint/definitions/core/proc.rb +2 -2
  128. data/lib/ruby-lint/definitions/core/process.rb +29 -29
  129. data/lib/ruby-lint/definitions/core/psych.rb +149 -149
  130. data/lib/ruby-lint/definitions/core/queue.rb +2 -2
  131. data/lib/ruby-lint/definitions/core/rake.rb +117 -117
  132. data/lib/ruby-lint/definitions/core/rake_file_utils.rb +1 -1
  133. data/lib/ruby-lint/definitions/core/rakeversion.rb +1 -1
  134. data/lib/ruby-lint/definitions/core/random.rb +2 -2
  135. data/lib/ruby-lint/definitions/core/range.rb +4 -4
  136. data/lib/ruby-lint/definitions/core/range_error.rb +2 -2
  137. data/lib/ruby-lint/definitions/core/rational.rb +2 -2
  138. data/lib/ruby-lint/definitions/core/rb_config.rb +3 -3
  139. data/lib/ruby-lint/definitions/core/regexp.rb +28 -28
  140. data/lib/ruby-lint/definitions/core/regexp_error.rb +2 -2
  141. data/lib/ruby-lint/definitions/core/rubinius.rb +1057 -1057
  142. data/lib/ruby-lint/definitions/core/ruby_copyright.rb +1 -1
  143. data/lib/ruby-lint/definitions/core/ruby_description.rb +1 -1
  144. data/lib/ruby-lint/definitions/core/ruby_engine.rb +1 -1
  145. data/lib/ruby-lint/definitions/core/ruby_lint.rb +9 -9
  146. data/lib/ruby-lint/definitions/core/ruby_patchlevel.rb +1 -1
  147. data/lib/ruby-lint/definitions/core/ruby_platform.rb +1 -1
  148. data/lib/ruby-lint/definitions/core/ruby_release_date.rb +1 -1
  149. data/lib/ruby-lint/definitions/core/ruby_version.rb +1 -1
  150. data/lib/ruby-lint/definitions/core/runtime_error.rb +2 -2
  151. data/lib/ruby-lint/definitions/core/scan_error.rb +2 -2
  152. data/lib/ruby-lint/definitions/core/script_error.rb +2 -2
  153. data/lib/ruby-lint/definitions/core/security_error.rb +2 -2
  154. data/lib/ruby-lint/definitions/core/shellwords.rb +1 -1
  155. data/lib/ruby-lint/definitions/core/signal.rb +3 -3
  156. data/lib/ruby-lint/definitions/core/signal_exception.rb +2 -2
  157. data/lib/ruby-lint/definitions/core/singleton.rb +2 -2
  158. data/lib/ruby-lint/definitions/core/sized_queue.rb +2 -2
  159. data/lib/ruby-lint/definitions/core/standard_error.rb +2 -2
  160. data/lib/ruby-lint/definitions/core/stderr.rb +1 -1
  161. data/lib/ruby-lint/definitions/core/stdin.rb +1 -1
  162. data/lib/ruby-lint/definitions/core/stdout.rb +1 -1
  163. data/lib/ruby-lint/definitions/core/stop_iteration.rb +2 -2
  164. data/lib/ruby-lint/definitions/core/string.rb +21 -21
  165. data/lib/ruby-lint/definitions/core/string_io.rb +7 -7
  166. data/lib/ruby-lint/definitions/core/string_scanner.rb +4 -4
  167. data/lib/ruby-lint/definitions/core/struct.rb +20 -20
  168. data/lib/ruby-lint/definitions/core/syck.rb +4 -4
  169. data/lib/ruby-lint/definitions/core/symbol.rb +2 -2
  170. data/lib/ruby-lint/definitions/core/syntax_error.rb +2 -2
  171. data/lib/ruby-lint/definitions/core/system_call_error.rb +2 -2
  172. data/lib/ruby-lint/definitions/core/system_exit.rb +2 -2
  173. data/lib/ruby-lint/definitions/core/system_stack_error.rb +2 -2
  174. data/lib/ruby-lint/definitions/core/thread.rb +6 -6
  175. data/lib/ruby-lint/definitions/core/thread_error.rb +2 -2
  176. data/lib/ruby-lint/definitions/core/thread_group.rb +2 -2
  177. data/lib/ruby-lint/definitions/core/time.rb +3 -3
  178. data/lib/ruby-lint/definitions/core/toplevel_binding.rb +1 -1
  179. data/lib/ruby-lint/definitions/core/true.rb +1 -1
  180. data/lib/ruby-lint/definitions/core/true_class.rb +2 -2
  181. data/lib/ruby-lint/definitions/core/type_error.rb +2 -2
  182. data/lib/ruby-lint/definitions/core/unbound_method.rb +2 -2
  183. data/lib/ruby-lint/definitions/core/unmarshalable.rb +1 -1
  184. data/lib/ruby-lint/definitions/core/unsupported_library_error.rb +2 -2
  185. data/lib/ruby-lint/definitions/core/weak_ref.rb +4 -4
  186. data/lib/ruby-lint/definitions/core/zero_division_error.rb +2 -2
  187. data/lib/ruby-lint/definitions/rails.rb +12 -0
  188. data/lib/ruby-lint/definitions/rails/abstract_controller.rb +335 -0
  189. data/lib/ruby-lint/definitions/rails/action_controller.rb +1244 -0
  190. data/lib/ruby-lint/definitions/rails/action_dispatch.rb +741 -0
  191. data/lib/ruby-lint/definitions/rails/action_mailer.rb +502 -0
  192. data/lib/ruby-lint/definitions/rails/action_pack.rb +16 -0
  193. data/lib/ruby-lint/definitions/rails/action_view.rb +898 -0
  194. data/lib/ruby-lint/definitions/rails/active_model.rb +437 -0
  195. data/lib/ruby-lint/definitions/rails/active_record.rb +2901 -0
  196. data/lib/ruby-lint/definitions/rails/active_support.rb +1963 -0
  197. data/lib/ruby-lint/definitions/rails/arel.rb +665 -0
  198. data/lib/ruby-lint/definitions/rails/rails.rb +452 -0
  199. data/lib/ruby-lint/definitions/rails/sprockets.rb +968 -0
  200. data/lib/ruby-lint/generated_constant.rb +33 -0
  201. data/lib/ruby-lint/helper/constant_paths.rb +30 -21
  202. data/lib/ruby-lint/inspector.rb +20 -2
  203. data/lib/ruby-lint/iterator.rb +11 -171
  204. data/lib/ruby-lint/nested_stack.rb +46 -0
  205. data/lib/ruby-lint/parser.rb +24 -806
  206. data/lib/ruby-lint/report.rb +2 -30
  207. data/lib/ruby-lint/report/entry.rb +2 -2
  208. data/lib/ruby-lint/runner.rb +81 -0
  209. data/lib/ruby-lint/template/definition.erb +12 -8
  210. data/lib/ruby-lint/variable_predicates.rb +16 -58
  211. data/lib/ruby-lint/version.rb +1 -1
  212. data/lib/ruby-lint/virtual_machine.rb +1044 -0
  213. data/ruby-lint.gemspec +17 -7
  214. data/spec/fixtures/complex/rails/basic_controller.rb +9 -0
  215. data/spec/fixtures/complex/rcap.rb +38 -0
  216. data/spec/fixtures/complex/slop.rb +680 -0
  217. data/spec/fixtures/config.yml +8 -0
  218. data/spec/fixtures/invalid.rb +3 -0
  219. data/spec/fixtures/invalid_2.rb +3 -0
  220. data/spec/fixtures/syntax_error.rb +1 -0
  221. data/spec/fixtures/valid.rb +3 -0
  222. data/spec/helper.rb +6 -0
  223. data/spec/ruby-lint/{analyze → analysis}/argument_amount.rb +7 -7
  224. data/spec/ruby-lint/analysis/confusing_variables.rb +46 -0
  225. data/spec/ruby-lint/analysis/pedantics.rb +43 -0
  226. data/spec/ruby-lint/{analyze → analysis}/shadowing_variables.rb +5 -5
  227. data/spec/ruby-lint/{analyze → analysis}/undefined_methods.rb +18 -18
  228. data/spec/ruby-lint/{analyze → analysis}/undefined_variables.rb +19 -25
  229. data/spec/ruby-lint/{analyze → analysis}/unused_variables.rb +29 -16
  230. data/spec/ruby-lint/ast/node.rb +33 -0
  231. data/spec/ruby-lint/cli/analyze.rb +31 -0
  232. data/spec/ruby-lint/cli/ast.rb +23 -0
  233. data/spec/ruby-lint/configuration.rb +45 -6
  234. data/spec/ruby-lint/definition/constant_proxy.rb +31 -0
  235. data/spec/ruby-lint/definition/dsl.rb +13 -20
  236. data/spec/ruby-lint/definition/ruby_method.rb +65 -148
  237. data/spec/ruby-lint/definition/ruby_object.rb +60 -96
  238. data/spec/ruby-lint/definition_builder/primitive.rb +62 -0
  239. data/spec/ruby-lint/definition_builder/ruby_class.rb +108 -0
  240. data/spec/ruby-lint/definition_builder/ruby_method.rb +53 -0
  241. data/spec/ruby-lint/definition_builder/ruby_module.rb +50 -0
  242. data/spec/ruby-lint/iterator.rb +40 -16
  243. data/spec/ruby-lint/nested_stack.rb +23 -0
  244. data/spec/ruby-lint/parser.rb +14 -0
  245. data/spec/ruby-lint/report.rb +0 -10
  246. data/spec/ruby-lint/report/entry.rb +8 -4
  247. data/spec/ruby-lint/runner.rb +32 -0
  248. data/spec/ruby-lint/virtual_machine/assignments/arrays.rb +87 -0
  249. data/spec/ruby-lint/virtual_machine/assignments/hashes.rb +52 -0
  250. data/spec/ruby-lint/virtual_machine/assignments/optional.rb +41 -0
  251. data/spec/ruby-lint/{definitions_builder → virtual_machine}/assignments/return_values.rb +11 -11
  252. data/spec/ruby-lint/virtual_machine/assignments/variables.rb +85 -0
  253. data/spec/ruby-lint/virtual_machine/associate_nodes.rb +17 -0
  254. data/spec/ruby-lint/virtual_machine/autoloading.rb +31 -0
  255. data/spec/ruby-lint/virtual_machine/blocks.rb +64 -0
  256. data/spec/ruby-lint/virtual_machine/classes/class_methods.rb +21 -0
  257. data/spec/ruby-lint/virtual_machine/classes/extending.rb +104 -0
  258. data/spec/ruby-lint/virtual_machine/classes/redefining.rb +24 -0
  259. data/spec/ruby-lint/virtual_machine/classes/sclass.rb +94 -0
  260. data/spec/ruby-lint/virtual_machine/classes/scoping.rb +60 -0
  261. data/spec/ruby-lint/virtual_machine/complex/rails.rb +18 -0
  262. data/spec/ruby-lint/virtual_machine/complex/rcap.rb +15 -0
  263. data/spec/ruby-lint/virtual_machine/complex/slop.rb +16 -0
  264. data/spec/ruby-lint/{definitions_builder → virtual_machine}/for.rb +2 -2
  265. data/spec/ruby-lint/virtual_machine/freeze.rb +13 -0
  266. data/spec/ruby-lint/virtual_machine/interpolation.rb +12 -0
  267. data/spec/ruby-lint/virtual_machine/methods/defining.rb +40 -0
  268. data/spec/ruby-lint/virtual_machine/methods/exporting.rb +19 -0
  269. data/spec/ruby-lint/virtual_machine/methods/parameters.rb +77 -0
  270. data/spec/ruby-lint/virtual_machine/methods/patching.rb +26 -0
  271. data/spec/ruby-lint/virtual_machine/methods/scoping.rb +63 -0
  272. data/spec/ruby-lint/virtual_machine/methods/visibility.rb +64 -0
  273. data/spec/ruby-lint/{definitions_builder → virtual_machine}/modules.rb +16 -16
  274. data/spec/ruby-lint/virtual_machine/reference_amount.rb +33 -0
  275. data/spec/ruby-lint/virtual_machine/unused.rb +17 -0
  276. data/spec/support/bacon.rb +13 -13
  277. data/spec/support/building.rb +23 -16
  278. data/spec/support/coveralls.rb +5 -0
  279. data/spec/support/fixtures.rb +20 -0
  280. data/spec/support/parsing.rb +3 -5
  281. data/spec/support/simplecov.rb +5 -3
  282. data/task/build.rake +1 -1
  283. data/task/cop.rake +11 -0
  284. data/task/generate.rake +40 -2
  285. data/task/profile.rake +27 -0
  286. data/task/todo.rake +6 -0
  287. data/task/travis.rake +7 -0
  288. metadata +160 -75
  289. metadata.gz.asc +14 -14
  290. data/doc/build/.gitkeep +0 -0
  291. data/lib/ruby-lint/analyze/argument_amount.rb +0 -73
  292. data/lib/ruby-lint/analyze/shadowing_variables.rb +0 -32
  293. data/lib/ruby-lint/analyze/undefined_methods.rb +0 -68
  294. data/lib/ruby-lint/analyze/undefined_variables.rb +0 -72
  295. data/lib/ruby-lint/analyze/unused_variables.rb +0 -48
  296. data/lib/ruby-lint/base.rb +0 -85
  297. data/lib/ruby-lint/definitions_builder.rb +0 -692
  298. data/lib/ruby-lint/helper/conversion.rb +0 -33
  299. data/lib/ruby-lint/helper/current_scope.rb +0 -98
  300. data/lib/ruby-lint/helper/methods.rb +0 -91
  301. data/lib/ruby-lint/node.rb +0 -107
  302. data/lib/ruby-lint/parser_error.rb +0 -30
  303. data/spec/ruby-lint/constant_loader.rb +0 -32
  304. data/spec/ruby-lint/definition/method_calls.rb +0 -26
  305. data/spec/ruby-lint/definitions_builder/assignments/arrays.rb +0 -71
  306. data/spec/ruby-lint/definitions_builder/assignments/hashes.rb +0 -65
  307. data/spec/ruby-lint/definitions_builder/assignments/objects.rb +0 -23
  308. data/spec/ruby-lint/definitions_builder/assignments/optional.rb +0 -22
  309. data/spec/ruby-lint/definitions_builder/assignments/variables.rb +0 -71
  310. data/spec/ruby-lint/definitions_builder/associate_nodes.rb +0 -17
  311. data/spec/ruby-lint/definitions_builder/blocks.rb +0 -40
  312. data/spec/ruby-lint/definitions_builder/classes.rb +0 -230
  313. data/spec/ruby-lint/definitions_builder/methods.rb +0 -147
  314. data/spec/ruby-lint/definitions_builder/reference_amount.rb +0 -31
  315. data/spec/ruby-lint/definitions_builder/unused.rb +0 -15
  316. data/spec/ruby-lint/node.rb +0 -38
  317. data/spec/ruby-lint/parser/assignments.rb +0 -225
  318. data/spec/ruby-lint/parser/classes.rb +0 -110
  319. data/spec/ruby-lint/parser/errors.rb +0 -12
  320. data/spec/ruby-lint/parser/metadata.rb +0 -17
  321. data/spec/ruby-lint/parser/method_definitions.rb +0 -111
  322. data/spec/ruby-lint/parser/methods.rb +0 -217
  323. data/spec/ruby-lint/parser/modules.rb +0 -70
  324. data/spec/ruby-lint/parser/operators.rb +0 -40
  325. data/spec/ruby-lint/parser/statements/begin.rb +0 -55
  326. data/spec/ruby-lint/parser/statements/case.rb +0 -34
  327. data/spec/ruby-lint/parser/statements/defined.rb +0 -11
  328. data/spec/ruby-lint/parser/statements/for.rb +0 -34
  329. data/spec/ruby-lint/parser/statements/if.rb +0 -46
  330. data/spec/ruby-lint/parser/statements/return.rb +0 -14
  331. data/spec/ruby-lint/parser/statements/super.rb +0 -49
  332. data/spec/ruby-lint/parser/statements/unless.rb +0 -42
  333. data/spec/ruby-lint/parser/statements/until.rb +0 -25
  334. data/spec/ruby-lint/parser/statements/while.rb +0 -25
  335. data/spec/ruby-lint/parser/statements/yield.rb +0 -18
  336. data/spec/ruby-lint/parser/types/arrays.rb +0 -47
  337. data/spec/ruby-lint/parser/types/booleans.rb +0 -11
  338. data/spec/ruby-lint/parser/types/constants.rb +0 -32
  339. data/spec/ruby-lint/parser/types/hashes.rb +0 -55
  340. data/spec/ruby-lint/parser/types/nil.rb +0 -7
  341. data/spec/ruby-lint/parser/types/numbers.rb +0 -11
  342. data/spec/ruby-lint/parser/types/procs.rb +0 -11
  343. data/spec/ruby-lint/parser/types/ranges.rb +0 -11
  344. data/spec/ruby-lint/parser/types/regexp.rb +0 -27
  345. data/spec/ruby-lint/parser/types/strings.rb +0 -44
  346. data/spec/ruby-lint/parser/types/symbols.rb +0 -15
  347. data/task/stdlib.rake +0 -23
@@ -55,40 +55,12 @@ module RubyLint
55
55
  #
56
56
  # @return [Array]
57
57
  #
58
- DEFAULT_LEVELS = [:error, :warning, :info]
59
-
60
- ##
61
- # Adds a new reporting level to the list of available levels.
62
- #
63
- # @param [#to_sym] level The reporting level to add.
64
- #
65
- def self.add_level(level)
66
- levels << level.to_sym
67
- end
68
-
69
- ##
70
- # Deletes a reporting level from the list of available levels. This does
71
- # not affect existing instances of this class.
72
- #
73
- # @param [#to_sym] level The level to delete.
74
- #
75
- def self.delete_level(level)
76
- levels.delete(level.to_sym)
77
- end
78
-
79
- ##
80
- # Returns a list of the available reporting levels.
81
- #
82
- # @return [Array]
83
- #
84
- def self.levels
85
- return @levels ||= DEFAULT_LEVELS.dup
86
- end
58
+ DEFAULT_LEVELS = [:error, :warning, :info].freeze
87
59
 
88
60
  ##
89
61
  # @param [Array] levels The reporting levels to enable for this instance.
90
62
  #
91
- def initialize(levels = self.class.levels)
63
+ def initialize(levels = DEFAULT_LEVELS)
92
64
  @levels = levels.map(&:to_sym)
93
65
  @entries = []
94
66
  end
@@ -57,14 +57,14 @@ module RubyLint
57
57
 
58
58
  ##
59
59
  # Determines the sort order of the current entry. The entry is sorted
60
- # based on the filename and the reporting level.
60
+ # based on the filename and the line.
61
61
  #
62
62
  # @param [RubyLint::Report::Entry] other The entry to compare with the
63
63
  # current one.
64
64
  # @return [Numeric]
65
65
  #
66
66
  def <=>(other)
67
- return (filename <=> other.filename) <=> (other.level <=> level)
67
+ return (filename <=> other.filename) <=> (other.line <=> line)
68
68
  end
69
69
  end # Entry
70
70
  end # Report
@@ -0,0 +1,81 @@
1
+ module RubyLint
2
+ ##
3
+ # {RubyLint::Runner} acts as an easy to use layer around the various parts of
4
+ # ruby-lint. Pass it some files and a {RubyLint::Configuration} object and it
5
+ # will take care of running code analysis, formatting it, etc.
6
+ #
7
+ # @!attribute [r] configuration
8
+ # @return [RubyLint::Configuration]
9
+ #
10
+ class Runner
11
+ attr_reader :configuration
12
+
13
+ ##
14
+ # @param [RubyLint::Configuration] configuration
15
+ #
16
+ def initialize(configuration)
17
+ @configuration = configuration
18
+ end
19
+
20
+ ##
21
+ # Analyses the given files and returns the report results.
22
+ #
23
+ # @param [Array] files
24
+ # @return [String]
25
+ #
26
+ def analyze(files)
27
+ report = Report.new(configuration.report_levels)
28
+ presenter = configuration.presenter.new
29
+ parser = Parser.new
30
+
31
+ parser.consumer = proc do |diag|
32
+ report_diagnostic(diag, report)
33
+
34
+ # FIXME: there's a bug in the pure Ruby version of Racc causing it hang
35
+ # after detecting a syntax error (it stays forever in recovery mode).
36
+ # To work around this we'll have to bail out after detecting the first
37
+ # syntax error.
38
+ return presenter.present(report)
39
+ end
40
+
41
+ files.each do |file|
42
+ code = File.read(file)
43
+ ast = parser.parse(code, file)
44
+ vm = RubyLint::VirtualMachine.new
45
+
46
+ vm.run(ast)
47
+
48
+ run_analysis(ast, vm, report)
49
+ end
50
+
51
+ return presenter.present(report)
52
+ end
53
+
54
+ private
55
+
56
+ ##
57
+ # @param [Parser::Diagnostic] diagnostic
58
+ # @param [RubyLint::Report] report
59
+ #
60
+ def report_diagnostic(diagnostic, report)
61
+ loc = diagnostic.location
62
+ buffer = loc.source_buffer
63
+
64
+ report.error(diagnostic.message, loc.line, loc.column, buffer.name)
65
+ end
66
+
67
+ ##
68
+ # Runs all the registered analysis classes.
69
+ #
70
+ # @param [RubyLint::AST::Node] ast
71
+ # @param [RubyLint::VirtualMachine] vm
72
+ # @param [RubyLint::Report] report
73
+ #
74
+ def run_analysis(ast, vm, report)
75
+ configuration.analysis_classes.each do |const|
76
+ instance = const.new(:vm => vm, :report => report)
77
+ instance.iterate(ast)
78
+ end
79
+ end
80
+ end # Runner
81
+ end # RubyLint
@@ -1,13 +1,16 @@
1
- ##
2
- # Constant: <%= @constant_name %>
1
+ # This file was automatically generated, any manual changes will be lost the
2
+ # next time this file is generated.
3
+ #
3
4
  # Created: <%= Time.new %>
4
5
  # Platform: <%= RUBY_ENGINE %> <%= Rubinius::VERSION rescue RUBY_VERSION %>
5
- #
6
- RubyLint.global_scope.define_constant('<%= @constant_name %>') do |klass|
7
- <%- if @superclass -%>
8
- klass.inherits(RubyLint.global_constant('<%= @superclass %>'))
6
+
7
+ <% @constants.each do |constant| %>
8
+ RubyLint::VirtualMachine.global_scope.define_constant('<%= constant.name %>') do |klass|
9
+ <%- if constant.superclass -%>
10
+ klass.inherits(RubyLint::VirtualMachine.constant_proxy('<%= constant.superclass %>'))
9
11
  <%- end -%>
10
- <%- @methods.each do |type, collection| -%>
12
+
13
+ <%- constant.methods.each do |type, collection| -%>
11
14
  <%- collection.each do |name, args| -%>
12
15
 
13
16
  <%- if args.empty? -%>
@@ -15,10 +18,11 @@ RubyLint.global_scope.define_constant('<%= @constant_name %>') do |klass|
15
18
  <%- else -%>
16
19
  klass.define_<%= type %>('<%= name %>') do |method|
17
20
  <%- args.each do |arg| -%>
18
- method.define_<%= arg[:method] %>('<%= arg[:name] %>')
21
+ method.define_<%= arg[:type] %>('<%= arg[:name] %>')
19
22
  <%- end -%>
20
23
  end
21
24
  <%- end -%>
22
25
  <%- end -%>
23
26
  <%- end -%>
24
27
  end
28
+ <% end %>
@@ -4,44 +4,20 @@ module RubyLint
4
4
  # types.
5
5
  #
6
6
  module VariablePredicates
7
- ##
8
- # Array containing the various variable types that are available in Ruby.
9
- #
10
- # @return [Array]
11
- #
12
- VARIABLE_TYPES = [
13
- :local_variable,
14
- :instance_variable,
15
- :class_variable,
16
- :global_variable
17
- ]
18
-
19
7
  ##
20
8
  # Array containing various Ruby types that are considered to be scalar
21
9
  # values.
22
10
  #
23
11
  # @return [Array]
24
12
  #
25
- SCALAR_TYPES = [:integer, :float, :string, :symbol]
13
+ SCALAR_TYPES = [:int, :float, :str, :sym]
26
14
 
27
15
  ##
28
16
  # Array containing various predicate methods to create.
29
17
  #
30
18
  # @return [Array]
31
19
  #
32
- PREDICATE_METHODS = [
33
- :aref,
34
- :array,
35
- :class,
36
- :constant,
37
- :constant_path,
38
- :hash,
39
- :identifier,
40
- :keyword,
41
- :method,
42
- :method_definition,
43
- :module
44
- ]
20
+ PREDICATE_METHODS = [:array, :class, :const, :hash, :module, :self, :block]
45
21
 
46
22
  ##
47
23
  # Hash containing various Node types and the associated Ruby classes.
@@ -49,54 +25,36 @@ module RubyLint
49
25
  # @return [Hash]
50
26
  #
51
27
  RUBY_CLASSES = {
52
- :string => 'String',
53
- :symbol => 'Symbol',
54
- :integer => 'Fixnum',
55
- :float => 'Float',
56
- :regexp => 'Regexp',
57
- :array => 'Array',
58
- :hash => 'Hash',
59
- :range => 'Range',
60
- :lambda => 'Proc'
28
+ :str => 'String',
29
+ :sym => 'Symbol',
30
+ :int => 'Fixnum',
31
+ :float => 'Float',
32
+ :regexp => 'Regexp',
33
+ :array => 'Array',
34
+ :hash => 'Hash',
35
+ :irange => 'Range',
36
+ :erange => 'Range',
37
+ :lambda => 'Proc'
61
38
  }
62
39
 
63
- (VARIABLE_TYPES + PREDICATE_METHODS).each do |type|
40
+ PREDICATE_METHODS.each do |type|
64
41
  define_method("#{type}?") do
65
42
  return @type == type
66
43
  end
67
44
  end
68
45
 
69
- ##
70
- # Returns `true` if the current node is a variable node.
71
- #
72
- # @return [TrueClass|FalseClass]
73
- #
74
- def variable?
75
- return VARIABLE_TYPES.include?(@type)
76
- end
77
-
78
46
  ##
79
47
  # @return [TrueClass|FalseClass]
80
48
  #
81
49
  def constant?
82
- return @type == :constant || @type == :module || @type == :class
83
- end
84
-
85
- ##
86
- # Returns `true` if the object type is a Ruby scalar such as a string or
87
- # integer.
88
- #
89
- def scalar?
90
- return SCALAR_TYPES.include?(@type)
50
+ return type == :const || type == :module || type == :class
91
51
  end
92
52
 
93
53
  ##
94
- # Indicates if the node is a collection of values.
95
- #
96
54
  # @return [TrueClass|FalseClass]
97
55
  #
98
- def collection?
99
- return array? || hash?
56
+ def constant_path?
57
+ return constant? && children[0].constant?
100
58
  end
101
59
 
102
60
  ##
@@ -1,3 +1,3 @@
1
1
  module RubyLint
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end # RubyLint
@@ -0,0 +1,1044 @@
1
+ module RubyLint
2
+ ##
3
+ # {RubyLint::VirtualMachine} is the heart of ruby-lint. It takes a AST
4
+ # generated by {RubyLint::Parser}, iterates it and builds various definitions
5
+ # of methods, variables, etc.
6
+ #
7
+ # The virtual machine is a stack based virtual machine. Whenever certain
8
+ # expressions are processed their values are stored in a stack which is then
9
+ # later used for creating definitions (where applicable). For example, when
10
+ # creating a new class a definition for the class is pushed on to a stack.
11
+ # All code defined in this class is then stored in the definition at the end
12
+ # of the stack.
13
+ #
14
+ # After a certain AST has been processed the VM will enter a read-only state
15
+ # to prevent code from modifying it (either on purpose or by accident).
16
+ #
17
+ # ## Stacks
18
+ #
19
+ # The virtual machine uses two stacks:
20
+ #
21
+ # * `value_stack`
22
+ # * `variable_stack`
23
+ #
24
+ # The value stack is used for storing raw values (e.g. integers) while the
25
+ # variable stack is used for storing variable definitions (which in turn
26
+ # store their values inside themselves).
27
+ #
28
+ # ## Definitions
29
+ #
30
+ # Built definitions are stored in {RubyLint::VirtualMachine#definitions} as a
31
+ # single root definition called "root". This definition in turn contains
32
+ # everything defined in a block of code that was processed by the VM.
33
+ #
34
+ # ## Associations
35
+ #
36
+ # The VM also keeps track of various nodes and their corresponding
37
+ # definitions to make it easier to retrieve them later on. These are only
38
+ # nodes/definitions related to a new scope such as a class or method
39
+ # definition node.
40
+ #
41
+ # These associations are stored as a Hash in
42
+ # {RubyLint::VirtualMachine#associations} with the keys set to the nodes and
43
+ # the values to the corresponding definitions.
44
+ #
45
+ # @!attribute [r] associations
46
+ # @return [Hash]
47
+ # @!attribute [r] definitions
48
+ # @return [RubyLint::Definition::RubyObject]
49
+ # @!attribute [r] value_stack
50
+ # @return [RubyLint::NestedStack]
51
+ # @!attribute [r] variable_stack
52
+ # @return [RubyLint::NestedStack]
53
+ #
54
+ class VirtualMachine < Iterator
55
+ include Helper::ConstantPaths
56
+
57
+ attr_reader :associations, :definitions, :value_stack, :variable_stack
58
+
59
+ private :value_stack, :variable_stack
60
+
61
+ ##
62
+ # Hash containing the definition types to copy when including/extending a
63
+ # module.
64
+ #
65
+ # @return [Hash]
66
+ #
67
+ INCLUDE_CALLS = {
68
+ 'include' => {
69
+ :const => :const,
70
+ :instance_method => :instance_method
71
+ },
72
+ 'extend' => {
73
+ :const => :const,
74
+ :instance_method => :method
75
+ }
76
+ }
77
+
78
+ ##
79
+ # Hash containing variable assignment types and the corresponding variable
80
+ # reference types.
81
+ #
82
+ # @return [Hash]
83
+ #
84
+ ASSIGNMENT_TYPES = {
85
+ :lvasgn => :lvar,
86
+ :ivasgn => :ivar,
87
+ :cvasgn => :cvar,
88
+ :gvasgn => :gvar
89
+ }
90
+
91
+ ##
92
+ # Collection of primitive value types.
93
+ #
94
+ # @return [Array]
95
+ #
96
+ PRIMITIVES = [:int, :float, :str, :sym]
97
+
98
+ ##
99
+ # Remaps the names for `on_send` callback nodes in cases where the original
100
+ # name of a method could not be used. For example, `on_send_[]=` is
101
+ # considered to be invalid syntax and thus its mapped to
102
+ # `on_send_assign_member`.
103
+ #
104
+ # @return [Hash]
105
+ #
106
+ SEND_MAPPING = {'[]=' => 'assign_member'}
107
+
108
+ ##
109
+ # Array containing the various argument types of method definitions.
110
+ #
111
+ # @return [Array]
112
+ #
113
+ ARGUMENT_TYPES = [:arg, :optarg, :restarg, :blockarg]
114
+
115
+ ##
116
+ # The types of variables to export outside of a method definition.
117
+ #
118
+ # @return [Array]
119
+ #
120
+ EXPORT_VARIABLES = [:ivar, :cvar, :const]
121
+
122
+ ##
123
+ # Array containing the directories to use for looking up definition files.
124
+ #
125
+ # @return [Array]
126
+ #
127
+ LOAD_PATH = [File.expand_path('../definitions/core', __FILE__)]
128
+
129
+ ##
130
+ # The available method visibilities.
131
+ #
132
+ # @return [Array]
133
+ #
134
+ VISIBILITIES = [:public, :protected, :private].freeze
135
+
136
+ ##
137
+ # @return [RubyLint::Definition::RubyObject]
138
+ #
139
+ def self.global_scope
140
+ return @global_scope ||= Definition::RubyObject.new(
141
+ :name => 'global',
142
+ :type => :global
143
+ )
144
+ end
145
+
146
+ ##
147
+ # Looks up the given constant in the global scope. If it does not exist
148
+ # this method will try to load it from one of the existing definitions.
149
+ #
150
+ # @param [String] name
151
+ # @return [RubyLint::Definition::RubyObject]
152
+ #
153
+ def self.global_constant(name)
154
+ found = global_scope.lookup_constant_path(name)
155
+
156
+ if !found and !constant_loader.loaded?(name)
157
+ constant_loader.load_constant(name)
158
+
159
+ found = global_scope.lookup_constant_path(name)
160
+ end
161
+
162
+ return found
163
+ end
164
+
165
+ ##
166
+ # Creates a new proxy for a global constant.
167
+ #
168
+ # @param [String] name The name of the constant, can include an entire
169
+ # constant path in the form of `Foo::Bar`.
170
+ # @return [RubyLint::Definition::ConstantProxy]
171
+ #
172
+ def self.constant_proxy(name)
173
+ return Definition::ConstantProxy.new(global_scope, name)
174
+ end
175
+
176
+ ##
177
+ # @return [RubyLint::ConstantLoader]
178
+ #
179
+ def self.constant_loader
180
+ return @constant_loader ||= ConstantLoader.new
181
+ end
182
+
183
+ ##
184
+ # Called after a new instance of the virtual machine has been created.
185
+ #
186
+ def after_initialize
187
+ @associations = {}
188
+ @definitions = initial_definitions
189
+ @scopes = [@definitions]
190
+ @in_sclass = false
191
+ @value_stack = NestedStack.new
192
+ @variable_stack = NestedStack.new
193
+ @ignored_nodes = []
194
+ @visibility = :public
195
+
196
+ reset_method_type
197
+ end
198
+
199
+ ##
200
+ # Processes the given AST. Constants are autoloaded first.
201
+ #
202
+ # @see #iterate
203
+ #
204
+ def run(ast)
205
+ self.class.constant_loader.iterate(ast)
206
+
207
+ iterate(ast)
208
+
209
+ freeze
210
+ end
211
+
212
+ ##
213
+ # Freezes the VM along with all the instance variables.
214
+ #
215
+ def freeze
216
+ super
217
+
218
+ instance_variables.each do |var|
219
+ instance_variable_get(var).freeze
220
+ end
221
+ end
222
+
223
+ ##
224
+ # @param [RubyLint::AST::Node] node
225
+ #
226
+ def on_root(node)
227
+ associate_node(node, current_scope)
228
+ end
229
+
230
+ ##
231
+ # Processes a regular variable assignment.
232
+ #
233
+ # @param [RubyLint::AST::Node] node
234
+ #
235
+ def on_assign(node)
236
+ reset_assignment_value
237
+ value_stack.add_stack
238
+ end
239
+
240
+ ##
241
+ # @see #on_assign
242
+ #
243
+ def after_assign(node)
244
+ type = ASSIGNMENT_TYPES[node.type]
245
+ name = node.children[0].to_s
246
+ value = value_stack.pop.first
247
+
248
+ if !value and assignment_value
249
+ value = assignment_value
250
+ end
251
+
252
+ assign_variable(type, name, value)
253
+ end
254
+
255
+ ASSIGNMENT_TYPES.each do |callback, type|
256
+ alias_method :"on_#{callback}", :on_assign
257
+ alias_method :"after_#{callback}", :after_assign
258
+ end
259
+
260
+ ##
261
+ # Processes the assignment of a constant.
262
+ #
263
+ # @param [RubyLint::AST::Node] node
264
+ #
265
+ def on_casgn(node)
266
+ # Don't push values for the receiver constant.
267
+ @ignored_nodes << node.children[0] if node.children[0]
268
+
269
+ reset_assignment_value
270
+ value_stack.add_stack
271
+ end
272
+
273
+ ##
274
+ # @see #on_casgn
275
+ #
276
+ def after_casgn(node)
277
+ values = value_stack.pop
278
+ scope = current_scope
279
+
280
+ if node.children[0]
281
+ scope = resolve_constant_path(node.children[0])
282
+
283
+ return unless scope
284
+ end
285
+
286
+ variable = Definition::RubyObject.new(
287
+ :type => :const,
288
+ :name => node.children[1].to_s,
289
+ :value => values.first,
290
+ :instance_type => :instance
291
+ )
292
+
293
+ add_variable(variable, scope)
294
+ end
295
+
296
+ ##
297
+ # @param [RubyLint::AST::Node] node
298
+ #
299
+ def on_masgn(node)
300
+ add_stacks
301
+ end
302
+
303
+ ##
304
+ # Processes a mass variable assignment using the stacks created by
305
+ # {#on_masgn}.
306
+ #
307
+ # @param [RubyLint::AST::Node] node
308
+ #
309
+ def after_masgn(node)
310
+ variables = variable_stack.pop
311
+ values = value_stack.pop.first
312
+ values = values ? values.value : []
313
+
314
+ variables.each_with_index do |variable, index|
315
+ variable.value = values[index].value if values[index]
316
+
317
+ current_scope.add(variable.type, variable.name, variable)
318
+ end
319
+ end
320
+
321
+ ##
322
+ # @param [RubyLint::AST::Node] node
323
+ #
324
+ def on_or_asgn(node)
325
+ add_stacks
326
+ end
327
+
328
+ ##
329
+ # Processes an `or` assignment in the form of `variable ||= value`.
330
+ #
331
+ # @param [RubyLint::AST::Node] node
332
+ #
333
+ def after_or_asgn(node)
334
+ variable = variable_stack.pop.first
335
+ value = value_stack.pop.first
336
+
337
+ if variable and value
338
+ conditional_assignment(variable, value, false)
339
+ end
340
+ end
341
+
342
+ ##
343
+ # @param [RubyLint::AST::Node] node
344
+ #
345
+ def on_and_asgn(node)
346
+ add_stacks
347
+ end
348
+
349
+ ##
350
+ # Processes an `and` assignment in the form of `variable &&= value`.
351
+ #
352
+ # @param [RubyLint::AST::Node] node
353
+ #
354
+ def after_and_asgn(node)
355
+ variable = variable_stack.pop.first
356
+ value = value_stack.pop.first
357
+
358
+ conditional_assignment(variable, value)
359
+ end
360
+
361
+ # Creates the callback methods for various primitives such as integers.
362
+ PRIMITIVES.each do |type|
363
+ define_method("on_#{type}") do |node|
364
+ push_value(create_primitive(node))
365
+ end
366
+ end
367
+
368
+ # Creates the callback methods for various variable types such as local
369
+ # variables.
370
+ ASSIGNMENT_TYPES.each do |asgn_name, type|
371
+ define_method("on_#{type}") do |node|
372
+ increment_reference_amount(node)
373
+ push_variable_value(node)
374
+ end
375
+ end
376
+
377
+ ##
378
+ # @param [RubyLint::AST::Node] node
379
+ #
380
+ def on_const(node)
381
+ increment_reference_amount(node)
382
+ push_variable_value(node)
383
+ end
384
+
385
+ ##
386
+ # @param [RubyLint::AST::Node] node
387
+ #
388
+ def on_array(node)
389
+ value_stack.add_stack
390
+ end
391
+
392
+ ##
393
+ # Builds an Array.
394
+ #
395
+ # @param [RubyLint::AST::Node] node
396
+ #
397
+ def after_array(node)
398
+ builder = DefinitionBuilder::RubyArray.new(
399
+ node,
400
+ current_scope,
401
+ :values => value_stack.pop
402
+ )
403
+
404
+ push_value(builder.build)
405
+ end
406
+
407
+ ##
408
+ # @param [RubyLint::AST::Node] node
409
+ #
410
+ def on_hash(node)
411
+ value_stack.add_stack
412
+ end
413
+
414
+ ##
415
+ # Builds a Hash.
416
+ #
417
+ # @param [RubyLint::AST::Node] node
418
+ #
419
+ def after_hash(node)
420
+ builder = DefinitionBuilder::RubyHash.new(
421
+ node,
422
+ current_scope,
423
+ :values => value_stack.pop
424
+ )
425
+
426
+ push_value(builder.build)
427
+ end
428
+
429
+ ##
430
+ # @param [RubyLint::AST::Node] node
431
+ #
432
+ def on_pair(node)
433
+ value_stack.add_stack
434
+ end
435
+
436
+ ##
437
+ # Processes a key/value pair.
438
+ #
439
+ # @param [RubyLint::AST::Node] node
440
+ #
441
+ def after_pair(node)
442
+ key, value = value_stack.pop
443
+
444
+ return unless key
445
+
446
+ member = Definition::RubyObject.new(
447
+ :name => key.value.to_s,
448
+ :type => :member,
449
+ :value => value
450
+ )
451
+
452
+ push_value(member)
453
+ end
454
+
455
+ ##
456
+ # @param [RubyLint::AST::Node] node
457
+ #
458
+ def on_self(node)
459
+ push_value(current_scope.lookup(:keyword, 'self'))
460
+ end
461
+
462
+ ##
463
+ # Creates the definition for a module.
464
+ #
465
+ # @param [RubyLint::AST::Node] node
466
+ #
467
+ def on_module(node)
468
+ define_module(node, DefinitionBuilder::RubyModule)
469
+ end
470
+
471
+ ##
472
+ # @param [RubyLint::AST::Node] node
473
+ #
474
+ def after_module(node)
475
+ pop_scope
476
+ end
477
+
478
+ ##
479
+ # Creates the definition for a class.
480
+ #
481
+ # @param [RubyLint::AST::Node] node
482
+ #
483
+ def on_class(node)
484
+ parent = nil
485
+ parent_node = node.children[1]
486
+
487
+ if parent_node
488
+ parent = evaluate_node(parent_node)
489
+
490
+ if !parent or !parent.const?
491
+ raise TypeError, 'classes can only inherit another class'
492
+ end
493
+ end
494
+
495
+ define_module(node, DefinitionBuilder::RubyClass, :parent => parent)
496
+ end
497
+
498
+ ##
499
+ # @param [RubyLint::AST::Node] node
500
+ #
501
+ def after_class(node)
502
+ pop_scope
503
+ end
504
+
505
+ ##
506
+ # Builds the definition for a block.
507
+ #
508
+ # @param [RubyLint::AST::Node] node
509
+ #
510
+ def on_block(node)
511
+ builder = DefinitionBuilder::RubyBlock.new(node, current_scope)
512
+ definition = builder.build
513
+
514
+ associate_node(node, definition)
515
+
516
+ push_scope(definition)
517
+ end
518
+
519
+ ##
520
+ # @param [RubyLint::AST::Node] node
521
+ #
522
+ def after_block(node)
523
+ pop_scope
524
+ end
525
+
526
+ ##
527
+ # Processes an sclass block. Sclass blocks look like the following:
528
+ #
529
+ # class << self
530
+ #
531
+ # end
532
+ #
533
+ # @param [RubyLint::AST::Node] node
534
+ #
535
+ def on_sclass(node)
536
+ parent = node.children[0]
537
+ definition = evaluate_node(parent)
538
+ @method_type = parent.self? ? :method : definition.method_call_type
539
+
540
+ associate_node(node, definition)
541
+
542
+ push_scope(definition)
543
+ end
544
+
545
+ ##
546
+ # @param [RubyLint::AST::Node] node
547
+ #
548
+ def after_sclass(node)
549
+ reset_method_type
550
+ pop_scope
551
+ end
552
+
553
+ ##
554
+ # Creates the definition for a method definition.
555
+ #
556
+ # @param [RubyLint::AST::Node] node
557
+ #
558
+ def on_def(node)
559
+ receiver = nil
560
+
561
+ if node.type == :defs
562
+ receiver = evaluate_node(node.children[0])
563
+ end
564
+
565
+ builder = DefinitionBuilder::RubyMethod.new(
566
+ node,
567
+ current_scope,
568
+ :type => @method_type,
569
+ :receiver => receiver,
570
+ :visibility => @visibility
571
+ )
572
+
573
+ definition = builder.build
574
+
575
+ builder.scope.add_definition(definition)
576
+
577
+ associate_node(node, definition)
578
+
579
+ push_scope(definition)
580
+ end
581
+
582
+ ##
583
+ # Exports various variables to the outer scope of the method definition.
584
+ #
585
+ # @param [RubyLint::AST::Node] node
586
+ #
587
+ def after_def(node)
588
+ previous = pop_scope
589
+ current = current_scope
590
+
591
+ EXPORT_VARIABLES.each do |type|
592
+ current.copy(previous, type)
593
+ end
594
+ end
595
+
596
+ ##
597
+ # @param [RubyLint::AST::Node] node
598
+ #
599
+ def on_args(node)
600
+ variable_stack.add_stack
601
+ end
602
+
603
+ ##
604
+ # @param [RubyLint::AST::Node] node
605
+ #
606
+ def after_args(node)
607
+ variables = variable_stack.pop
608
+
609
+ variables.each do |variable|
610
+ current_scope.add_definition(variable)
611
+ end
612
+ end
613
+
614
+ # Creates callbacks for various argument types such as :arg and :optarg.
615
+ ARGUMENT_TYPES.each do |type|
616
+ define_method("on_#{type}") do |node|
617
+ value_stack.add_stack
618
+ end
619
+
620
+ define_method("after_#{type}") do |node|
621
+ value = value_stack.pop.first
622
+ name = node.children[0].to_s
623
+ arg = Definition::RubyObject.new(
624
+ :type => type,
625
+ :name => name,
626
+ :value => value,
627
+ :instance_type => :instance
628
+ )
629
+
630
+ current_scope.add_definition(arg)
631
+
632
+ assign_variable(:lvar, name, value)
633
+ end
634
+ end
635
+
636
+ alias_method :on_defs, :on_def
637
+ alias_method :after_defs, :after_def
638
+
639
+ ##
640
+ # Processes a method call. If a certain method call has its own dedicated
641
+ # callback that one will be called as well.
642
+ #
643
+ # @param [RubyLint::AST::Node] node
644
+ #
645
+ def on_send(node)
646
+ name = node.children[1].to_s
647
+ name = SEND_MAPPING.fetch(name, name)
648
+ callback = "on_send_#{name}"
649
+
650
+ value_stack.add_stack
651
+
652
+ execute_callback(callback, node)
653
+ end
654
+
655
+ ##
656
+ # @param [RubyLint::AST::Node] node
657
+ #
658
+ def after_send(node)
659
+ receiver, name, _ = *node
660
+
661
+ name = name.to_s
662
+ mapped_name = SEND_MAPPING.fetch(name, name)
663
+ callback = "after_send_#{mapped_name}"
664
+
665
+ execute_callback(callback, node)
666
+
667
+ receiver_and_args = value_stack.pop
668
+
669
+ if receiver
670
+ context = receiver_and_args.shift
671
+ else
672
+ context = current_scope
673
+
674
+ # `parser` wraps (block) nodes around (send) calls which is a bit
675
+ # inconvenient
676
+ context = previous_scope if context.block?
677
+ end
678
+
679
+ # Associate the receiver node with the context so that it becomes
680
+ # easier to retrieve later on.
681
+ if receiver && context
682
+ associate_node(receiver, context)
683
+ end
684
+
685
+ if context and context.method_defined?(name)
686
+ retval = context.call_method(name)
687
+
688
+ push_value(retval)
689
+ end
690
+ end
691
+
692
+ ##
693
+ # @param [RubyLint::AST::Node] node
694
+ #
695
+ def on_send_include(node)
696
+ value_stack.add_stack
697
+ end
698
+
699
+ ##
700
+ # Processes a `include` method call.
701
+ #
702
+ # @param [RubyLint::AST::Node] node
703
+ #
704
+ def after_send_include(node)
705
+ copy_types = INCLUDE_CALLS[node.children[1].to_s]
706
+ scope = current_scope
707
+ arguments = value_stack.pop
708
+
709
+ arguments.each do |source|
710
+ copy_types.each do |from, to|
711
+ source.list(from).each do |definition|
712
+ scope.add(to, definition.name, definition)
713
+ end
714
+ end
715
+ end
716
+ end
717
+
718
+ alias_method :on_send_extend, :on_send_include
719
+ alias_method :after_send_extend, :after_send_include
720
+
721
+ VISIBILITIES.each do |vis|
722
+ define_method("on_send_#{vis}") do |node|
723
+ @visibility = vis
724
+ end
725
+ end
726
+
727
+ ##
728
+ # @param [RubyLint::AST::Node] node
729
+ #
730
+ def on_send_assign_member(node)
731
+ value_stack.add_stack
732
+ end
733
+
734
+ ##
735
+ # Processes the assignment of an object member (array index or hash key).
736
+ #
737
+ # @param [RubyLint::AST::Node] node
738
+ #
739
+ def after_send_assign_member(node)
740
+ array, *indexes, values = value_stack.pop
741
+ index_values = []
742
+
743
+ if values and values.array?
744
+ index_values = values.list(:member).map(&:value)
745
+ elsif values
746
+ index_values = [values]
747
+ end
748
+
749
+ indexes.each do |index|
750
+ member = Definition::RubyObject.new(
751
+ :name => index.value.to_s,
752
+ :type => :member,
753
+ :value => index_values.shift
754
+ )
755
+
756
+ array.add_definition(member)
757
+ end
758
+ end
759
+
760
+ private
761
+
762
+ ##
763
+ # Returns the initial set of definitions to use.
764
+ #
765
+ # @return [RubyLint::Definition::RubyObject]
766
+ #
767
+ def initial_definitions
768
+ definitions = Definition::RubyObject.new(
769
+ :name => 'root',
770
+ :type => :root,
771
+ :parents => [RubyLint::VirtualMachine.global_constant('Kernel')],
772
+ :instance_type => :instance
773
+ )
774
+
775
+ definitions.merge(RubyLint::VirtualMachine.global_scope)
776
+
777
+ definitions.add(:keyword, 'self', definitions)
778
+
779
+ return definitions
780
+ end
781
+
782
+ ##
783
+ # Defines a new module/class based on the supplied node.
784
+ #
785
+ # @param [RubyLint::Node] node
786
+ # @param [Class] definition_builder
787
+ # @param [Hash] options
788
+ #
789
+ def define_module(node, definition_builder, options = {})
790
+ builder = definition_builder.new(node, current_scope, options)
791
+ definition = builder.build
792
+ scope = builder.scope
793
+ existing = scope.lookup(definition.type, definition.name)
794
+
795
+ if existing
796
+ definition = existing
797
+
798
+ inherit_definition(definition, current_scope)
799
+ else
800
+ scope.add_definition(definition)
801
+ end
802
+
803
+ associate_node(node, definition)
804
+
805
+ push_scope(definition)
806
+ end
807
+
808
+ ##
809
+ # @return [RubyLint::Definition::RubyObject]
810
+ #
811
+ def current_scope
812
+ return @scopes.last
813
+ end
814
+
815
+ ##
816
+ # @return [RubyLint::Definition::RubyObject]
817
+ #
818
+ def previous_scope
819
+ return @scopes[-2]
820
+ end
821
+
822
+ ##
823
+ # Associates the given node and defintion with each other.
824
+ #
825
+ # @param [RubyLint::AST::Node] node
826
+ # @param [RubyLint::Definition::RubyObject] definition
827
+ #
828
+ def associate_node(node, definition)
829
+ @associations[node] = definition
830
+ end
831
+
832
+ ##
833
+ # Pushes a new scope on the list of available scopes.
834
+ #
835
+ # @param [RubyLint::Definition::RubyObject] definition
836
+ #
837
+ def push_scope(definition)
838
+ unless definition.is_a?(RubyLint::Definition::RubyObject)
839
+ raise(
840
+ ArgumentError,
841
+ "Expected a RubyLint::Definition::RubyObject but got " \
842
+ "#{definition.class} instead"
843
+ )
844
+ end
845
+
846
+ @scopes << definition
847
+ end
848
+
849
+ ##
850
+ # Removes a scope from the list.
851
+ #
852
+ def pop_scope
853
+ raise 'Trying to pop an empty scope' if @scopes.empty?
854
+
855
+ @scopes.pop
856
+ end
857
+
858
+ ##
859
+ # Pushes the value of a variable onto the value stack.
860
+ #
861
+ # @param [RubyLint::AST::Node] node
862
+ #
863
+ def push_variable_value(node)
864
+ return if value_stack.empty? || @ignored_nodes.include?(node)
865
+
866
+ definition = definition_for_node(node)
867
+
868
+ if definition
869
+ value = definition.value ? definition.value : definition
870
+
871
+ push_value(value)
872
+ end
873
+ end
874
+
875
+ ##
876
+ # Pushes a definition (of a value) onto the value stack.
877
+ #
878
+ # @param [RubyLint::Definition::RubyObject] definition
879
+ #
880
+ def push_value(definition)
881
+ value_stack.push(definition) if definition && !value_stack.empty?
882
+ end
883
+
884
+ ##
885
+ # Adds a new variable and value stack.
886
+ #
887
+ def add_stacks
888
+ variable_stack.add_stack
889
+ value_stack.add_stack
890
+ end
891
+
892
+ ##
893
+ # Assigns a basic variable.
894
+ #
895
+ # @param [Symbol] type The type of variable.
896
+ # @param [String] name The name of the variable
897
+ # @param [RubyLint::Definition::RubyObject] value
898
+ #
899
+ def assign_variable(type, name, value)
900
+ variable = Definition::RubyObject.new(
901
+ :type => type,
902
+ :name => name,
903
+ :value => value,
904
+ :instance_type => :instance
905
+ )
906
+
907
+ buffer_assignment_value(variable.value)
908
+
909
+ add_variable(variable)
910
+ end
911
+
912
+ ##
913
+ # Adds a variable to the current scope of, if a the variable stack is not
914
+ # empty, add it to the stack instead.
915
+ #
916
+ # @param [RubyLint::Definition::RubyObject] variable
917
+ # @param [RubyLint::Definition::RubyObject] scope
918
+ #
919
+ def add_variable(variable, scope = current_scope)
920
+ if variable_stack.empty?
921
+ scope.add(variable.type, variable.name, variable)
922
+ else
923
+ variable_stack.push(variable)
924
+ end
925
+ end
926
+
927
+ ##
928
+ # Creates a primitive value such as an integer.
929
+ #
930
+ # @param [RubyLint::AST::Node] node
931
+ # @param [Hash] options
932
+ #
933
+ def create_primitive(node, options = {})
934
+ builder = DefinitionBuilder::Primitive.new(node, current_scope, options)
935
+
936
+ return builder.build
937
+ end
938
+
939
+ ##
940
+ # Resets the variable used for storing the last assignment value.
941
+ #
942
+ def reset_assignment_value
943
+ @assignment_value = nil
944
+ end
945
+
946
+ ##
947
+ # Returns the value of the last assignment.
948
+ #
949
+ def assignment_value
950
+ return @assignment_value
951
+ end
952
+
953
+ ##
954
+ # Stores the value as the last assigned value.
955
+ #
956
+ # @param [RubyLint::Definition::RubyObject] value
957
+ #
958
+ def buffer_assignment_value(value)
959
+ @assignment_value = value
960
+ end
961
+
962
+ ##
963
+ # Resets the method assignment/call type.
964
+ #
965
+ def reset_method_type
966
+ @method_type = :instance_method
967
+ end
968
+
969
+ ##
970
+ # Performs a conditional assignment.
971
+ #
972
+ # @param [RubyLint::Definition::RubyObject] variable
973
+ # @param [RubyLint::Definition::RubyValue] value
974
+ # @param [TrueClass|FalseClass] bool When set to `true` existing variables
975
+ # will be overwritten.
976
+ #
977
+ def conditional_assignment(variable, value, bool = true)
978
+ if current_scope.has_definition?(variable.type, variable.name) == bool
979
+ variable.value = value
980
+
981
+ current_scope.add_definition(variable)
982
+
983
+ buffer_assignment_value(variable.value)
984
+ end
985
+ end
986
+
987
+ ##
988
+ # Returns the definition for the given node.
989
+ #
990
+ # @param [RubyLint::AST::Node] node
991
+ # @return [RubyLint::Definition::RubyObject]
992
+ #
993
+ def definition_for_node(node)
994
+ if node.const? and node.children[0]
995
+ definition = resolve_constant_path(node)
996
+ else
997
+ definition = current_scope.lookup(node.type, node.name)
998
+ end
999
+
1000
+ return definition
1001
+ end
1002
+
1003
+ ##
1004
+ # Increments the reference amount of a node's definition unless the
1005
+ # definition is frozen.
1006
+ #
1007
+ # @param [RubyLint::AST::Node] node
1008
+ #
1009
+ def increment_reference_amount(node)
1010
+ definition = definition_for_node(node)
1011
+
1012
+ if definition and !definition.frozen?
1013
+ definition.reference_amount += 1
1014
+ end
1015
+ end
1016
+
1017
+ ##
1018
+ # Evaluates and returns the value of the given node.
1019
+ #
1020
+ # @param [RubyLint::AST::Node] node
1021
+ # @return [RubyLint::Definition::RubyObject]
1022
+ #
1023
+ def evaluate_node(node)
1024
+ value_stack.add_stack
1025
+
1026
+ iterate(node)
1027
+
1028
+ return value_stack.pop.first
1029
+ end
1030
+
1031
+ ##
1032
+ # Includes the definition `inherit` in the list of parent definitions of
1033
+ # `definition`.
1034
+ #
1035
+ # @param [RubyLint::Definition::RubyObject] definition
1036
+ # @param [RubyLint::Definition::RubyObject] inherit
1037
+ #
1038
+ def inherit_definition(definition, inherit)
1039
+ unless definition.parents.include?(inherit)
1040
+ definition.parents << inherit
1041
+ end
1042
+ end
1043
+ end # VirtualMachine
1044
+ end # RubyLint