ruby-lint 0.0.3 → 0.0.4

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 (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