ruby-lint 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. data.tar.gz.asc +17 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +25 -0
  4. data/.yardopts +4 -0
  5. data/Gemfile +1 -1
  6. data/LICENSE +1 -1
  7. data/MANIFEST +238 -49
  8. data/README.md +84 -131
  9. data/Rakefile +6 -0
  10. data/bin/ruby-lint +2 -2
  11. data/checksum/.gitkeep +0 -0
  12. data/doc/DCO.md +26 -0
  13. data/doc/architecture.md +63 -0
  14. data/doc/code_analysis.md +90 -0
  15. data/doc/configuration.md +86 -0
  16. data/doc/contributing.md +16 -0
  17. data/doc/graphviz/flow.dot +7 -0
  18. data/doc/images/.gitkeep +0 -0
  19. data/doc/images/flow.png +0 -0
  20. data/lib/ruby-lint.rb +35 -35
  21. data/lib/ruby-lint/analyze/argument_amount.rb +73 -0
  22. data/lib/ruby-lint/analyze/shadowing_variables.rb +19 -24
  23. data/lib/ruby-lint/analyze/undefined_methods.rb +68 -0
  24. data/lib/ruby-lint/analyze/undefined_variables.rb +42 -69
  25. data/lib/ruby-lint/analyze/unused_variables.rb +23 -78
  26. data/lib/ruby-lint/base.rb +85 -0
  27. data/lib/ruby-lint/cli.rb +23 -167
  28. data/lib/ruby-lint/cli/analyze.rb +99 -0
  29. data/lib/ruby-lint/cli/ast.rb +35 -0
  30. data/lib/ruby-lint/cli/base.rb +120 -0
  31. data/lib/ruby-lint/configuration.rb +112 -0
  32. data/lib/ruby-lint/constant_loader.rb +92 -0
  33. data/lib/ruby-lint/definition/ruby_method.rb +248 -0
  34. data/lib/ruby-lint/definition/ruby_object.rb +757 -0
  35. data/lib/ruby-lint/definition_generator.rb +155 -0
  36. data/lib/ruby-lint/definitions/core.rb +5 -0
  37. data/lib/ruby-lint/definitions/core/arg0.rb +7 -0
  38. data/lib/ruby-lint/definitions/core/argf.rb +7 -0
  39. data/lib/ruby-lint/definitions/core/argument_error.rb +12 -0
  40. data/lib/ruby-lint/definitions/core/argv.rb +7 -0
  41. data/lib/ruby-lint/definitions/core/array.rb +414 -0
  42. data/lib/ruby-lint/definitions/core/autoload.rb +39 -0
  43. data/lib/ruby-lint/definitions/core/basic_object.rb +46 -0
  44. data/lib/ruby-lint/definitions/core/bignum.rb +128 -0
  45. data/lib/ruby-lint/definitions/core/binding.rb +52 -0
  46. data/lib/ruby-lint/definitions/core/class.rb +23 -0
  47. data/lib/ruby-lint/definitions/core/comparable.rb +38 -0
  48. data/lib/ruby-lint/definitions/core/complex.rb +195 -0
  49. data/lib/ruby-lint/definitions/core/condition_variable.rb +19 -0
  50. data/lib/ruby-lint/definitions/core/continuation.rb +8 -0
  51. data/lib/ruby-lint/definitions/core/data.rb +8 -0
  52. data/lib/ruby-lint/definitions/core/date.rb +706 -0
  53. data/lib/ruby-lint/definitions/core/date_time.rb +381 -0
  54. data/lib/ruby-lint/definitions/core/default_record_separator.rb +7 -0
  55. data/lib/ruby-lint/definitions/core/digest.rb +166 -0
  56. data/lib/ruby-lint/definitions/core/dir.rb +496 -0
  57. data/lib/ruby-lint/definitions/core/encoding.rb +2030 -0
  58. data/lib/ruby-lint/definitions/core/encoding_error.rb +8 -0
  59. data/lib/ruby-lint/definitions/core/enumerable.rb +352 -0
  60. data/lib/ruby-lint/definitions/core/enumerator.rb +37 -0
  61. data/lib/ruby-lint/definitions/core/env.rb +7 -0
  62. data/lib/ruby-lint/definitions/core/eoferror.rb +8 -0
  63. data/lib/ruby-lint/definitions/core/erb.rb +304 -0
  64. data/lib/ruby-lint/definitions/core/errno.rb +3331 -0
  65. data/lib/ruby-lint/definitions/core/etc.rb +138 -0
  66. data/lib/ruby-lint/definitions/core/exception.rb +72 -0
  67. data/lib/ruby-lint/definitions/core/false.rb +7 -0
  68. data/lib/ruby-lint/definitions/core/false_class.rb +30 -0
  69. data/lib/ruby-lint/definitions/core/fatal_error.rb +8 -0
  70. data/lib/ruby-lint/definitions/core/fiber.rb +35 -0
  71. data/lib/ruby-lint/definitions/core/fiber_error.rb +8 -0
  72. data/lib/ruby-lint/definitions/core/file.rb +1277 -0
  73. data/lib/ruby-lint/definitions/core/file_list.rb +727 -0
  74. data/lib/ruby-lint/definitions/core/file_test.rb +106 -0
  75. data/lib/ruby-lint/definitions/core/file_utils.rb +1027 -0
  76. data/lib/ruby-lint/definitions/core/fixnum.rb +156 -0
  77. data/lib/ruby-lint/definitions/core/float.rb +307 -0
  78. data/lib/ruby-lint/definitions/core/float_domain_error.rb +8 -0
  79. data/lib/ruby-lint/definitions/core/gc.rb +57 -0
  80. data/lib/ruby-lint/definitions/core/gem.rb +3161 -0
  81. data/lib/ruby-lint/definitions/core/hash.rb +512 -0
  82. data/lib/ruby-lint/definitions/core/immediate_value.rb +19 -0
  83. data/lib/ruby-lint/definitions/core/index_error.rb +8 -0
  84. data/lib/ruby-lint/definitions/core/integer.rb +100 -0
  85. data/lib/ruby-lint/definitions/core/interrupt.rb +14 -0
  86. data/lib/ruby-lint/definitions/core/io.rb +928 -0
  87. data/lib/ruby-lint/definitions/core/ioerror.rb +8 -0
  88. data/lib/ruby-lint/definitions/core/kernel.rb +504 -0
  89. data/lib/ruby-lint/definitions/core/key_error.rb +8 -0
  90. data/lib/ruby-lint/definitions/core/load_error.rb +28 -0
  91. data/lib/ruby-lint/definitions/core/local_jump_error.rb +8 -0
  92. data/lib/ruby-lint/definitions/core/main.rb +25 -0
  93. data/lib/ruby-lint/definitions/core/marshal.rb +466 -0
  94. data/lib/ruby-lint/definitions/core/match_data.rb +73 -0
  95. data/lib/ruby-lint/definitions/core/math.rb +205 -0
  96. data/lib/ruby-lint/definitions/core/memory_segmention_error.rb +8 -0
  97. data/lib/ruby-lint/definitions/core/method.rb +61 -0
  98. data/lib/ruby-lint/definitions/core/module.rb +262 -0
  99. data/lib/ruby-lint/definitions/core/monitor.rb +39 -0
  100. data/lib/ruby-lint/definitions/core/monitor_mixin.rb +59 -0
  101. data/lib/ruby-lint/definitions/core/mutex.rb +32 -0
  102. data/lib/ruby-lint/definitions/core/name_error.rb +16 -0
  103. data/lib/ruby-lint/definitions/core/nil.rb +7 -0
  104. data/lib/ruby-lint/definitions/core/nil_class.rb +46 -0
  105. data/lib/ruby-lint/definitions/core/no_memory_error.rb +8 -0
  106. data/lib/ruby-lint/definitions/core/no_method_error.rb +18 -0
  107. data/lib/ruby-lint/definitions/core/not_implemented_error.rb +8 -0
  108. data/lib/ruby-lint/definitions/core/numeric.rb +123 -0
  109. data/lib/ruby-lint/definitions/core/object.rb +31 -0
  110. data/lib/ruby-lint/definitions/core/object_space.rb +41 -0
  111. data/lib/ruby-lint/definitions/core/open_struct.rb +49 -0
  112. data/lib/ruby-lint/definitions/core/option_parser.rb +1355 -0
  113. data/lib/ruby-lint/definitions/core/precision.rb +21 -0
  114. data/lib/ruby-lint/definitions/core/primitive_failure.rb +8 -0
  115. data/lib/ruby-lint/definitions/core/proc.rb +109 -0
  116. data/lib/ruby-lint/definitions/core/process.rb +602 -0
  117. data/lib/ruby-lint/definitions/core/psych.rb +2231 -0
  118. data/lib/ruby-lint/definitions/core/queue.rb +44 -0
  119. data/lib/ruby-lint/definitions/core/rake.rb +4784 -0
  120. data/lib/ruby-lint/definitions/core/rake_file_utils.rb +203 -0
  121. data/lib/ruby-lint/definitions/core/rakeversion.rb +7 -0
  122. data/lib/ruby-lint/definitions/core/random.rb +38 -0
  123. data/lib/ruby-lint/definitions/core/range.rb +104 -0
  124. data/lib/ruby-lint/definitions/core/range_error.rb +8 -0
  125. data/lib/ruby-lint/definitions/core/rational.rb +96 -0
  126. data/lib/ruby-lint/definitions/core/rb_config.rb +36 -0
  127. data/lib/ruby-lint/definitions/core/regexp.rb +396 -0
  128. data/lib/ruby-lint/definitions/core/regexp_error.rb +8 -0
  129. data/lib/ruby-lint/definitions/core/rubinius.rb +16637 -0
  130. data/lib/ruby-lint/definitions/core/ruby_copyright.rb +7 -0
  131. data/lib/ruby-lint/definitions/core/ruby_description.rb +7 -0
  132. data/lib/ruby-lint/definitions/core/ruby_engine.rb +7 -0
  133. data/lib/ruby-lint/definitions/core/ruby_lint.rb +93 -0
  134. data/lib/ruby-lint/definitions/core/ruby_patchlevel.rb +7 -0
  135. data/lib/ruby-lint/definitions/core/ruby_platform.rb +7 -0
  136. data/lib/ruby-lint/definitions/core/ruby_release_date.rb +7 -0
  137. data/lib/ruby-lint/definitions/core/ruby_version.rb +7 -0
  138. data/lib/ruby-lint/definitions/core/runtime_error.rb +8 -0
  139. data/lib/ruby-lint/definitions/core/scan_error.rb +8 -0
  140. data/lib/ruby-lint/definitions/core/script_error.rb +8 -0
  141. data/lib/ruby-lint/definitions/core/security_error.rb +8 -0
  142. data/lib/ruby-lint/definitions/core/shellwords.rb +37 -0
  143. data/lib/ruby-lint/definitions/core/signal.rb +37 -0
  144. data/lib/ruby-lint/definitions/core/signal_exception.rb +19 -0
  145. data/lib/ruby-lint/definitions/core/singleton.rb +37 -0
  146. data/lib/ruby-lint/definitions/core/sized_queue.rb +42 -0
  147. data/lib/ruby-lint/definitions/core/standard_error.rb +8 -0
  148. data/lib/ruby-lint/definitions/core/stderr.rb +7 -0
  149. data/lib/ruby-lint/definitions/core/stdin.rb +7 -0
  150. data/lib/ruby-lint/definitions/core/stdout.rb +7 -0
  151. data/lib/ruby-lint/definitions/core/stop_iteration.rb +8 -0
  152. data/lib/ruby-lint/definitions/core/string.rb +713 -0
  153. data/lib/ruby-lint/definitions/core/string_io.rb +287 -0
  154. data/lib/ruby-lint/definitions/core/string_scanner.rb +158 -0
  155. data/lib/ruby-lint/definitions/core/struct.rb +357 -0
  156. data/lib/ruby-lint/definitions/core/syck.rb +30 -0
  157. data/lib/ruby-lint/definitions/core/symbol.rb +90 -0
  158. data/lib/ruby-lint/definitions/core/syntax_error.rb +44 -0
  159. data/lib/ruby-lint/definitions/core/system_call_error.rb +31 -0
  160. data/lib/ruby-lint/definitions/core/system_exit.rb +19 -0
  161. data/lib/ruby-lint/definitions/core/system_stack_error.rb +8 -0
  162. data/lib/ruby-lint/definitions/core/thread.rb +209 -0
  163. data/lib/ruby-lint/definitions/core/thread_error.rb +8 -0
  164. data/lib/ruby-lint/definitions/core/thread_group.rb +22 -0
  165. data/lib/ruby-lint/definitions/core/time.rb +233 -0
  166. data/lib/ruby-lint/definitions/core/toplevel_binding.rb +7 -0
  167. data/lib/ruby-lint/definitions/core/true.rb +7 -0
  168. data/lib/ruby-lint/definitions/core/true_class.rb +30 -0
  169. data/lib/ruby-lint/definitions/core/type_error.rb +8 -0
  170. data/lib/ruby-lint/definitions/core/unbound_method.rb +51 -0
  171. data/lib/ruby-lint/definitions/core/unmarshalable.rb +13 -0
  172. data/lib/ruby-lint/definitions/core/unsupported_library_error.rb +8 -0
  173. data/lib/ruby-lint/definitions/core/weak_ref.rb +42 -0
  174. data/lib/ruby-lint/definitions/core/zero_division_error.rb +8 -0
  175. data/lib/ruby-lint/definitions_builder.rb +692 -0
  176. data/lib/ruby-lint/extensions/string.rb +15 -0
  177. data/lib/ruby-lint/helper/constant_paths.rb +41 -0
  178. data/lib/ruby-lint/helper/conversion.rb +33 -0
  179. data/lib/ruby-lint/helper/current_scope.rb +98 -0
  180. data/lib/ruby-lint/helper/methods.rb +91 -0
  181. data/lib/ruby-lint/inspector.rb +191 -0
  182. data/lib/ruby-lint/iterator.rb +187 -127
  183. data/lib/ruby-lint/node.rb +107 -0
  184. data/lib/ruby-lint/parser.rb +510 -1137
  185. data/lib/ruby-lint/parser_error.rb +15 -27
  186. data/lib/ruby-lint/presenter/json.rb +19 -0
  187. data/lib/ruby-lint/presenter/text.rb +37 -0
  188. data/lib/ruby-lint/report.rb +95 -53
  189. data/lib/ruby-lint/report/entry.rb +71 -0
  190. data/lib/ruby-lint/template/definition.erb +24 -0
  191. data/lib/ruby-lint/template/scope.rb +25 -0
  192. data/lib/ruby-lint/variable_predicates.rb +109 -0
  193. data/lib/ruby-lint/version.rb +1 -1
  194. data/ruby-lint.gemspec +19 -8
  195. data/spec/helper.rb +10 -2
  196. data/spec/ruby-lint/analyze/argument_amount.rb +91 -0
  197. data/spec/ruby-lint/analyze/shadowing_variables.rb +69 -14
  198. data/spec/ruby-lint/analyze/undefined_methods.rb +174 -0
  199. data/spec/ruby-lint/analyze/undefined_variables.rb +70 -179
  200. data/spec/ruby-lint/analyze/unused_variables.rb +63 -183
  201. data/spec/ruby-lint/configuration.rb +15 -0
  202. data/spec/ruby-lint/constant_loader.rb +32 -0
  203. data/spec/ruby-lint/definition/dsl.rb +142 -0
  204. data/spec/ruby-lint/definition/method_calls.rb +26 -0
  205. data/spec/ruby-lint/definition/ruby_method.rb +175 -0
  206. data/spec/ruby-lint/definition/ruby_object.rb +228 -0
  207. data/spec/ruby-lint/definitions_builder/assignments/arrays.rb +71 -0
  208. data/spec/ruby-lint/definitions_builder/assignments/hashes.rb +65 -0
  209. data/spec/ruby-lint/definitions_builder/assignments/objects.rb +23 -0
  210. data/spec/ruby-lint/definitions_builder/assignments/optional.rb +22 -0
  211. data/spec/ruby-lint/definitions_builder/assignments/return_values.rb +78 -0
  212. data/spec/ruby-lint/definitions_builder/assignments/variables.rb +71 -0
  213. data/spec/ruby-lint/definitions_builder/associate_nodes.rb +17 -0
  214. data/spec/ruby-lint/definitions_builder/blocks.rb +40 -0
  215. data/spec/ruby-lint/definitions_builder/classes.rb +230 -0
  216. data/spec/ruby-lint/definitions_builder/for.rb +16 -0
  217. data/spec/ruby-lint/definitions_builder/methods.rb +147 -0
  218. data/spec/ruby-lint/definitions_builder/modules.rb +175 -0
  219. data/spec/ruby-lint/definitions_builder/reference_amount.rb +31 -0
  220. data/spec/ruby-lint/definitions_builder/unused.rb +15 -0
  221. data/spec/ruby-lint/extensions/string.rb +7 -0
  222. data/spec/ruby-lint/iterator.rb +42 -417
  223. data/spec/ruby-lint/node.rb +38 -0
  224. data/spec/ruby-lint/parser/assignments.rb +225 -0
  225. data/spec/ruby-lint/parser/classes.rb +80 -122
  226. data/spec/ruby-lint/parser/errors.rb +7 -14
  227. data/spec/ruby-lint/parser/metadata.rb +17 -0
  228. data/spec/ruby-lint/parser/method_definitions.rb +111 -0
  229. data/spec/ruby-lint/parser/methods.rb +184 -216
  230. data/spec/ruby-lint/parser/modules.rb +54 -33
  231. data/spec/ruby-lint/parser/operators.rb +30 -65
  232. data/spec/ruby-lint/parser/statements/begin.rb +55 -0
  233. data/spec/ruby-lint/parser/statements/case.rb +34 -0
  234. data/spec/ruby-lint/parser/statements/defined.rb +11 -0
  235. data/spec/ruby-lint/parser/statements/for.rb +34 -0
  236. data/spec/ruby-lint/parser/statements/if.rb +46 -0
  237. data/spec/ruby-lint/parser/statements/return.rb +14 -0
  238. data/spec/ruby-lint/parser/statements/super.rb +49 -0
  239. data/spec/ruby-lint/parser/statements/unless.rb +42 -0
  240. data/spec/ruby-lint/parser/statements/until.rb +25 -0
  241. data/spec/ruby-lint/parser/statements/while.rb +25 -0
  242. data/spec/ruby-lint/parser/statements/yield.rb +18 -0
  243. data/spec/ruby-lint/parser/types/arrays.rb +47 -0
  244. data/spec/ruby-lint/parser/types/booleans.rb +11 -0
  245. data/spec/ruby-lint/parser/types/constants.rb +32 -0
  246. data/spec/ruby-lint/parser/types/hashes.rb +55 -0
  247. data/spec/ruby-lint/parser/types/nil.rb +7 -0
  248. data/spec/ruby-lint/parser/types/numbers.rb +11 -0
  249. data/spec/ruby-lint/parser/types/procs.rb +11 -0
  250. data/spec/ruby-lint/parser/types/ranges.rb +11 -0
  251. data/spec/ruby-lint/parser/types/regexp.rb +27 -0
  252. data/spec/ruby-lint/parser/types/strings.rb +44 -0
  253. data/spec/ruby-lint/parser/types/symbols.rb +15 -0
  254. data/spec/ruby-lint/presenter/json.rb +31 -0
  255. data/spec/ruby-lint/presenter/text.rb +22 -0
  256. data/spec/ruby-lint/report.rb +45 -15
  257. data/spec/ruby-lint/report/entry.rb +24 -0
  258. data/spec/support/bacon.rb +33 -0
  259. data/spec/support/building.rb +43 -0
  260. data/spec/support/definitions.rb +23 -0
  261. data/spec/support/parsing.rb +23 -0
  262. data/spec/support/simplecov.rb +16 -0
  263. data/task/build.rake +9 -0
  264. data/task/checksum.rake +13 -0
  265. data/task/coverage.rake +6 -0
  266. data/task/doc.rake +5 -0
  267. data/task/generate.rake +34 -0
  268. data/task/graphviz.rake +12 -0
  269. data/task/stdlib.rake +2 -9
  270. data/task/tag.rake +6 -0
  271. metadata +337 -68
  272. metadata.gz.asc +17 -0
  273. data/.rbenv-version +0 -1
  274. data/lib/ruby-lint/analyze/coding_style.rb +0 -407
  275. data/lib/ruby-lint/analyze/definitions.rb +0 -244
  276. data/lib/ruby-lint/analyze/method_validation.rb +0 -104
  277. data/lib/ruby-lint/callback.rb +0 -67
  278. data/lib/ruby-lint/constant_importer.rb +0 -112
  279. data/lib/ruby-lint/definition.rb +0 -230
  280. data/lib/ruby-lint/formatter/text.rb +0 -54
  281. data/lib/ruby-lint/helper/definition_resolver.rb +0 -143
  282. data/lib/ruby-lint/helper/scoping.rb +0 -138
  283. data/lib/ruby-lint/options.rb +0 -58
  284. data/lib/ruby-lint/token/assignment_token.rb +0 -35
  285. data/lib/ruby-lint/token/begin_rescue_token.rb +0 -57
  286. data/lib/ruby-lint/token/block_token.rb +0 -26
  287. data/lib/ruby-lint/token/case_token.rb +0 -44
  288. data/lib/ruby-lint/token/class_token.rb +0 -24
  289. data/lib/ruby-lint/token/keyword_token.rb +0 -43
  290. data/lib/ruby-lint/token/method_definition_token.rb +0 -64
  291. data/lib/ruby-lint/token/method_token.rb +0 -56
  292. data/lib/ruby-lint/token/parameters_token.rb +0 -99
  293. data/lib/ruby-lint/token/regexp_token.rb +0 -15
  294. data/lib/ruby-lint/token/statement_token.rb +0 -69
  295. data/lib/ruby-lint/token/token.rb +0 -176
  296. data/lib/ruby-lint/token/variable_token.rb +0 -18
  297. data/spec/benchmarks/memory.rb +0 -52
  298. data/spec/benchmarks/parse_parser.rb +0 -16
  299. data/spec/fixtures/stdlib/un.rb +0 -348
  300. data/spec/ruby-lint/analyze/coding_style.rb +0 -224
  301. data/spec/ruby-lint/analyze/complex/un.rb +0 -29
  302. data/spec/ruby-lint/analyze/definitions/classes.rb +0 -114
  303. data/spec/ruby-lint/analyze/definitions/methods.rb +0 -91
  304. data/spec/ruby-lint/analyze/definitions/modules.rb +0 -207
  305. data/spec/ruby-lint/analyze/definitions/variables.rb +0 -103
  306. data/spec/ruby-lint/analyze/method_validation.rb +0 -177
  307. data/spec/ruby-lint/callback.rb +0 -28
  308. data/spec/ruby-lint/constant_importer.rb +0 -27
  309. data/spec/ruby-lint/definition.rb +0 -96
  310. data/spec/ruby-lint/formatter/text.rb +0 -21
  311. data/spec/ruby-lint/parser/arrays.rb +0 -147
  312. data/spec/ruby-lint/parser/expander_assignments.rb +0 -183
  313. data/spec/ruby-lint/parser/hashes.rb +0 -136
  314. data/spec/ruby-lint/parser/keywords.rb +0 -89
  315. data/spec/ruby-lint/parser/objects.rb +0 -39
  316. data/spec/ruby-lint/parser/procs.rb +0 -113
  317. data/spec/ruby-lint/parser/ranges.rb +0 -49
  318. data/spec/ruby-lint/parser/regexp.rb +0 -31
  319. data/spec/ruby-lint/parser/scalars.rb +0 -93
  320. data/spec/ruby-lint/parser/statements.rb +0 -591
  321. data/spec/ruby-lint/parser/variables.rb +0 -230
@@ -0,0 +1,92 @@
1
+ module RubyLint
2
+ ##
3
+ # The ConstantLoader class tries to pre-load various constants in a given
4
+ # file before the definitions are being built and analysis is performed.
5
+ #
6
+ # Note that this pre-loader is rather basic and as such there are chances you
7
+ # still have to manually require definitions to ensure that they are being
8
+ # used.
9
+ #
10
+ # @!attribute [r] loaded
11
+ # @return [Hash] Hash containing the loaded constants.
12
+ #
13
+ class ConstantLoader < Iterator
14
+ attr_reader :loaded
15
+
16
+ ##
17
+ # List of directories to search for definition files.
18
+ #
19
+ # @return [Array]
20
+ #
21
+ LOAD_PATH = [
22
+ File.expand_path('../definitions/core', __FILE__)
23
+ ]
24
+
25
+ ##
26
+ # @see RubyLint::Iterator#initialize
27
+ #
28
+ def initialize(*args)
29
+ super
30
+
31
+ @loaded = {}
32
+ @in_constant_path = false
33
+ end
34
+
35
+ ##
36
+ # @param [RubyLint::Node] node
37
+ #
38
+ def on_constant_path(node)
39
+ @in_constant_path = true
40
+
41
+ load(node.children.first.name)
42
+ end
43
+
44
+ ##
45
+ # @param [RubyLint::Node] node
46
+ #
47
+ def after_constant_path(node)
48
+ @in_constant_path = false
49
+ end
50
+
51
+ ##
52
+ # @param [RubyLint::Node] node
53
+ #
54
+ def on_constant(node)
55
+ return if @in_constant_path
56
+
57
+ load(node.name)
58
+ end
59
+
60
+ ##
61
+ # Checks if the given constant is already loaded or not.
62
+ #
63
+ # @param [String] constant
64
+ # @return [TrueClass|FalseClass]
65
+ #
66
+ def loaded?(constant)
67
+ return loaded.key?(constant)
68
+ end
69
+
70
+ ##
71
+ # Tries to load the definitions for the given constant.
72
+ #
73
+ # @param [String] constant
74
+ #
75
+ def load(constant)
76
+ return if loaded?(constant)
77
+
78
+ filename = constant.snake_case + '.rb'
79
+
80
+ LOAD_PATH.each do |path|
81
+ path = File.join(path, filename)
82
+
83
+ if File.file?(path)
84
+ require(path)
85
+ loaded[constant] = true
86
+
87
+ break
88
+ end
89
+ end
90
+ end
91
+ end # ConstantLoader
92
+ end # RubyLint
@@ -0,0 +1,248 @@
1
+ module RubyLint
2
+ module Definition
3
+ ##
4
+ # The RubyMethod definition class is a definition class used for storing
5
+ # information about Ruby methods (both class and instance methods).
6
+ #
7
+ # @see RubyLint::Definition::RubyObject
8
+ #
9
+ # @!attribute [r] visibility
10
+ # @return [Symbol] The method visibility such as `:public`.
11
+ #
12
+ # @!attribute [r] arguments
13
+ # @return [Array] The required/specified arguments of a method definition
14
+ # or method call.
15
+ #
16
+ # @!attribute [r] optional_arguments
17
+ # @return [Array] Array containing the optional arguments of a method
18
+ # definition.
19
+ #
20
+ # @!attribute [r] rest_argument
21
+ # @return [RubyLint::Definition::RubyObject] The rest argument of a
22
+ # method definition.
23
+ #
24
+ # @!attribute [r] more_arguments
25
+ # @return [Array] A set of "more" arguments of the method definition.
26
+ #
27
+ # @!attribute [r] block_argument
28
+ # @return [RubyLint::Definition::RubyObject] The block argument of a
29
+ # method definition.
30
+ #
31
+ # @!attribute [r] method_type
32
+ # @return [Symbol] The type of method definition, set to `:method` for
33
+ # class methods and `:instance_method` for instance methods.
34
+ #
35
+ # @!attribute [r] return_value
36
+ # @return [Mixed] The value that is returned by the method.
37
+ #
38
+ class RubyMethod < RubyObject
39
+ ##
40
+ # Hash that contains the node types and attribute names to store the
41
+ # arguments in.
42
+ #
43
+ # @return [Hash]
44
+ #
45
+ ARGUMENT_TYPE_MAPPING = {
46
+ :argument => :arguments,
47
+ :optional_argument => :optional_arguments,
48
+ :rest_argument => :rest_argument,
49
+ :more_argument => :more_arguments,
50
+ :block_argument => :block_argument
51
+ }
52
+
53
+ attr_reader :block_argument,
54
+ :arguments,
55
+ :method_type,
56
+ :more_arguments,
57
+ :optional_arguments,
58
+ :rest_argument,
59
+ :return_value,
60
+ :visibility
61
+
62
+ ##
63
+ # @see RubyLint::Definition::RubyObject#new_from_node
64
+ #
65
+ def self.new_from_node(node, options = {})
66
+ options = default_method_options.merge(options)
67
+ options = options.merge(gather_arguments(node))
68
+ receiver = node.receiver
69
+
70
+ options[:method_type] ||= node.method_type
71
+
72
+ if receiver
73
+ options[:receiver] = RubyObject.new_from_node(receiver)
74
+ options[:method_type] = :method
75
+ end
76
+
77
+ return super(node, options)
78
+ end
79
+
80
+ ##
81
+ # Returns a Hash containing all the arguments grouped together based on
82
+ # their types.
83
+ #
84
+ # @param [RubyLint::Node] node
85
+ # @return [Hash]
86
+ #
87
+ def self.gather_arguments(node)
88
+ arguments = default_arguments
89
+
90
+ ARGUMENT_TYPE_MAPPING.each do |from, to|
91
+ args = node.gather_arguments(from)
92
+ args = args.map { |n| RubyObject.new_from_node(n, :value => n.value) }
93
+
94
+ arguments[to] = arguments[to].is_a?(Array) ? args : args[0]
95
+ end
96
+
97
+ return arguments
98
+ end
99
+
100
+ ##
101
+ # Returns the default Hash for a set of method arguments.
102
+ #
103
+ # @return [Hash]
104
+ #
105
+ def self.default_arguments
106
+ return {
107
+ :arguments => [],
108
+ :optional_arguments => [],
109
+ :rest_argument => nil,
110
+ :more_arguments => [],
111
+ :block_argument => nil
112
+ }
113
+ end
114
+
115
+ ##
116
+ # Returns a Hash containing the default options for this class. The name
117
+ # is different than {RubyLint::Definition::RubyObject#default_options} to
118
+ # prevent any naming issues.
119
+ #
120
+ # @return [Hash]
121
+ #
122
+ def self.default_method_options
123
+ return {:method_type => :instance_method}
124
+ end
125
+
126
+ ##
127
+ # @see RubyLint::Definition::RubyObject#initialize
128
+ #
129
+ def initialize(*args)
130
+ @arguments = []
131
+ @optional_arguments = []
132
+ @more_arguments = []
133
+
134
+ super
135
+
136
+ define_arguments unless method?
137
+ end
138
+
139
+ ##
140
+ # Sets the return value of this method. If a block is given it will be
141
+ # used as the return value. The block is *not* evaluated until it's
142
+ # called.
143
+ #
144
+ # @example
145
+ # string.define_instance_method(:gsub) do |method|
146
+ # method.returns('...')
147
+ # end
148
+ #
149
+ # @param [Mixed] value
150
+ #
151
+ def returns(value = nil, &block)
152
+ @return_value = block_given? ? block : value
153
+ end
154
+
155
+ ##
156
+ # Defines a required argument for the method.
157
+ #
158
+ # @example
159
+ # method.define_argument('number')
160
+ #
161
+ # @param [String] name The name of the argument.
162
+ #
163
+ def define_argument(name)
164
+ @arguments << create_variable(name)
165
+ end
166
+
167
+ ##
168
+ # Defines a optional argument for the method.
169
+ #
170
+ # @see RubyLint::Definition::RubyObject#define_argument
171
+ #
172
+ def define_optional_argument(name)
173
+ @optional_arguments << create_variable(name)
174
+ end
175
+
176
+ ##
177
+ # Defines a rest argument for the method.
178
+ #
179
+ # @see RubyLint::Definition::RubyObject#define_argument
180
+ #
181
+ def define_rest_argument(name)
182
+ @rest_argument = create_variable(name)
183
+ end
184
+
185
+ ##
186
+ # Defines a more argument for the method.
187
+ #
188
+ # @see RubyLint::Definition::RubyObject#define_argument
189
+ #
190
+ def define_more_argument(name)
191
+ @more_arguments << create_variable(name)
192
+ end
193
+
194
+ ##
195
+ # Defines a block argument for the method.
196
+ #
197
+ # @see RubyLint::Definition::RubyObject#define_argument
198
+ #
199
+ def define_block_argument(name)
200
+ @block_argument = create_variable(name)
201
+ end
202
+
203
+ private
204
+
205
+ ##
206
+ # Adds all the arguments of this method to the definitions list.
207
+ #
208
+ def define_arguments
209
+ all_arguments.each do |params|
210
+ next unless params
211
+
212
+ params.each do |param|
213
+ add(param.type, param.name, param) if param
214
+ end
215
+ end
216
+ end
217
+
218
+ ##
219
+ # Returns an Array containing all the method arguments. Each arguments
220
+ # set (even single ones such as the more argument) is returned as an
221
+ # Array making it easier to iterate over the collection.
222
+ #
223
+ # @return [Array]
224
+ #
225
+ def all_arguments
226
+ return [
227
+ arguments,
228
+ optional_arguments,
229
+ [rest_argument],
230
+ more_arguments,
231
+ [block_argument]
232
+ ]
233
+ end
234
+
235
+ ##
236
+ # @param [String] name
237
+ # @return [RubyLint::Definition::RubyObject]
238
+ #
239
+ def create_variable(name)
240
+ variable = RubyObject.new(:type => :local_variable, :name => name)
241
+
242
+ add(variable.type, variable.name, variable)
243
+
244
+ return variable
245
+ end
246
+ end # RubyMethod
247
+ end # Definition
248
+ end # RubyLint
@@ -0,0 +1,757 @@
1
+ module RubyLint
2
+ module Definition
3
+ ##
4
+ # The RubyObject class is the base definition class of ruby-lint. These so
5
+ # called definition classes are used for storing information about Ruby
6
+ # classes and instances. At their most basic form they are a mix between
7
+ # {RubyLint::Node} and a lookup table.
8
+ #
9
+ # ruby-lint currently provides the following two definition classes:
10
+ #
11
+ # * {RubyLint::Definition::RubyObject}: the base definition class, used for
12
+ # most Ruby types and values.
13
+ # * {RubyLint::Definition::RubyMethod} definition class that is used for
14
+ # methods exclusively.
15
+ #
16
+ # Using the RubyObject class one could create a definition for the String
17
+ # class as following:
18
+ #
19
+ # string = RubyObject.new(:name => 'String', :type => :constant)
20
+ # newline = RubyObject.new(
21
+ # :name => 'NEWLINE',
22
+ # :type => :constant,
23
+ # :value => "\n"
24
+ # )
25
+ #
26
+ # string.add(:constant, newline.name, newline)
27
+ #
28
+ # For more information see the documentation of the corresponding methods.
29
+ #
30
+ # @!attribute [r] name
31
+ # @return [String] The name of the object.
32
+ #
33
+ # @!attribute [rw] value
34
+ # @return [Mixed] The value of the object.
35
+ #
36
+ # @!attribute [r] type
37
+ # @return [Symbol] The type of object, e.g. `:constant`.
38
+ #
39
+ # @!attribute [r] ignore
40
+ # @return [TrueClass|FalseClass] When set to `true` the definition should
41
+ # be ignored by any analysis related code. This is mostly used when no
42
+ # meaningful data could be assigned (e.g. block arguments).
43
+ #
44
+ # @!attribute [r] definitions
45
+ # @return [Hash] Hash containing all child the definitions.
46
+ #
47
+ # @!attribute [rw] parents
48
+ # @return [Array] Array containing the parent definitions.
49
+ #
50
+ # @!attribute [rw] receiver
51
+ # @return [RubyLint::Definition::RubyObject] The receiver on which the
52
+ # object was defined/called.
53
+ #
54
+ # @!attribute [rw] reference_amount
55
+ # @return [Numeric] The amount of times an object was referenced.
56
+ # Currently this is only used for variables.
57
+ #
58
+ # @!attribute [rw] instance_type
59
+ # @return [Symbol] Indicates if the object represents a class or an
60
+ # instance.
61
+ #
62
+ # @!attribute [r] update_parents
63
+ # @return [Array] A list of data types to also add to the parent
64
+ # definitions when adding an object to the current one.
65
+ #
66
+ class RubyObject
67
+ include VariablePredicates
68
+
69
+ ##
70
+ # Array containing items that should be looked up in the parent
71
+ # definition if they're not found in the current one.
72
+ #
73
+ # @return [Array]
74
+ #
75
+ LOOKUP_PARENT = [
76
+ :class_variable,
77
+ :constant,
78
+ :global_variable,
79
+ :instance_method,
80
+ :instance_variable,
81
+ :keyword,
82
+ :method
83
+ ]
84
+
85
+ ##
86
+ # String used to separate segments in a constant path.
87
+ #
88
+ # @return [String]
89
+ #
90
+ PATH_SEPARATOR = '::'
91
+
92
+ attr_reader :update_parents,
93
+ :column,
94
+ :definitions,
95
+ :ignore,
96
+ :name,
97
+ :type,
98
+ :value
99
+
100
+ attr_accessor :instance_type,
101
+ :parents,
102
+ :receiver,
103
+ :reference_amount
104
+
105
+ ##
106
+ # Creates a new RubyObject instance based on an instance of
107
+ # {RubyLint::Node}. This method is primarily used in
108
+ # {RubyLint::DefinitionsBuilder}, in most cases third-party code should
109
+ # not have a need for this method.
110
+ #
111
+ # @param [RubyLint::Node] node
112
+ # @return [RubyLint::Definition::RubyObject]
113
+ #
114
+ def self.new_from_node(node, options = {})
115
+ path_segments = []
116
+
117
+ if node.constant_path?
118
+ path_segments = node.children[0..-2].reverse
119
+ node = node.children[-1]
120
+ end
121
+
122
+ options[:name] ||= node.name
123
+ options[:type] ||= node.type
124
+
125
+ # Checking to see if :value evaluates to `true` would mean you could
126
+ # never manually assign a nil value.
127
+ unless options.key?(:value)
128
+ options[:value] = node.value
129
+ end
130
+
131
+ if options[:value]
132
+ options[:value] = create_value_definitions(options[:value])
133
+ end
134
+
135
+ object = new(options)
136
+
137
+ # Assign the receivers of this object.
138
+ #
139
+ # TODO: this approach doesn't take existing definitions into account,
140
+ # instead it will always create a new one for each segment.
141
+ if !path_segments.empty? and !options[:receiver]
142
+ path_segments.inject(object) do |source, segment|
143
+ source.receiver = new_from_node(segment)
144
+ source.receiver
145
+ end
146
+ end
147
+
148
+ return object
149
+ end
150
+
151
+ ##
152
+ # Converts either a single {RubyLint::Node} instance or a collection of
153
+ # instances into {RubyObject} instances.
154
+ #
155
+ # @param [RubyLint::Node|Array<RubyLint::Node>] value
156
+ # @return [RubyLint::Node|Array<RubyLint::Node>]
157
+ #
158
+ def self.create_value_definitions(value)
159
+ if value.is_a?(Array)
160
+ value = value.map { |v| create_value_definitions(v) }
161
+ elsif value.is_a?(Node)
162
+ value = RubyObject.new_from_node(value)
163
+ end
164
+
165
+ return value
166
+ end
167
+
168
+ ##
169
+ # @example
170
+ # string = RubyObject.new(:name => 'String', :type => :constant)
171
+ #
172
+ # @param [Hash] options Hash containing additional options such as the
173
+ # parent definitions. For a list of available options see the
174
+ # corresponding getter/setter methods of this class.
175
+ #
176
+ # @yieldparam [RubyLint::Definition::RubyObject]
177
+ #
178
+ def initialize(options = {})
179
+ options = default_options.merge(options)
180
+
181
+ options.each do |key, value|
182
+ instance_variable_set("@#{key}", value)
183
+ end
184
+
185
+ clear!
186
+
187
+ yield self if block_given?
188
+ end
189
+
190
+ ##
191
+ # Sets the value of the definition. If a {RubyLint::Node} instance is
192
+ # specified it will be converted to a definition instance.
193
+ #
194
+ # @param [RubyLint::Definition::RubyObject|RubyLint::Node] value
195
+ #
196
+ def value=(value)
197
+ @value = value.is_a?(Node) ? RubyObject.new_from_node(value) : value
198
+ end
199
+
200
+ ##
201
+ # Adds a new definition to the definitions list.
202
+ #
203
+ # @example
204
+ # string = RubyObject.new(:name => 'String', :type => :constant)
205
+ # newline = RubyObject.new(
206
+ # :name => 'NEWLINE',
207
+ # :type => :constant,
208
+ # :value => "\n"
209
+ # )
210
+ #
211
+ # string.add(newline.type, newline.name, newline)
212
+ #
213
+ # @param [#to_sym] type The type of definition to add.
214
+ # @param [String] name The name of the definition.
215
+ # @param [RubyLint::Definition::RubyObject] value
216
+ #
217
+ # @raise [TypeError] Raised when a value that is not a RubyObject
218
+ # instance (or a subclass of this class) is given.
219
+ #
220
+ # @raise [ArgumentError] Raised when the specified type was invalid.
221
+ #
222
+ def add(type, name, value)
223
+ type = prepare_type(type)
224
+
225
+ unless value.is_a?(RubyObject)
226
+ raise TypeError, "Expected RubyObject but got #{value.class}"
227
+ end
228
+
229
+ unless definitions.key?(type)
230
+ raise ArgumentError, ":#{type} is not a valid type of data to add"
231
+ end
232
+
233
+ definitions[type][name] = value
234
+
235
+ if update_parents.include?(type)
236
+ update_parent_definitions(type, name, value)
237
+ end
238
+ end
239
+
240
+ ##
241
+ # Looks up a definition by the given type and name. If no data was found
242
+ # this method will try to look it up in any parent definitions.
243
+ #
244
+ # If no definition was found `nil` will be returned.
245
+ #
246
+ # @example
247
+ # string = RubyObject.new(:name => 'String', :type => :constant)
248
+ # newline = RubyObject.new(
249
+ # :name => 'NEWLINE',
250
+ # :type => :constant,
251
+ # :value => "\n"
252
+ # )
253
+ #
254
+ # string.add(newline.type, newline.name, newline)
255
+ #
256
+ # string.lookup(:constant, 'NEWLINE') # => #<RubyLint::Definition...>
257
+ #
258
+ # @param [#to_sym] type
259
+ # @param [String] name
260
+ # @return [RubyLint::Definition::RubyObject|NilClass]
261
+ #
262
+ def lookup(type, name)
263
+ type, name = prepare_lookup(type, name)
264
+ found = nil
265
+
266
+ if defines?(type, name)
267
+ found = definitions[type][name]
268
+
269
+ # Look up the definition in the parent scope(s) (if any are set).
270
+ elsif lookup_parent?(type)
271
+ parents.each do |parent|
272
+ parent_definition = parent.lookup(type, name)
273
+
274
+ if parent_definition
275
+ found = parent_definition
276
+ break
277
+ end
278
+ end
279
+ end
280
+
281
+ return found
282
+ end
283
+
284
+ ##
285
+ # Returns the definition for the given constant path. If one of the
286
+ # segments does not exist an error is raised instead.
287
+ #
288
+ # @example
289
+ # example.lookup_constant_path('A::B') # => #<RubyLint::Definition...>
290
+ #
291
+ # @param [String|Array<String>] path
292
+ # @return [RubyLint::Definition::RubyObject]
293
+ # @raise [ArgumentError] Raised when an invalid constant path is
294
+ # specified.
295
+ #
296
+ def lookup_constant_path(path)
297
+ constant = self
298
+ path = path.split(PATH_SEPARATOR) if path.is_a?(String)
299
+
300
+ path.each do |segment|
301
+ found = constant.lookup(:constant, segment)
302
+
303
+ if found
304
+ constant = found
305
+ else
306
+ name = path.join(PATH_SEPARATOR)
307
+
308
+ raise ArgumentError, "Invalid constant path: #{name}"
309
+ end
310
+ end
311
+
312
+ return constant
313
+ end
314
+
315
+ ##
316
+ # Mimics a method call based on the given method name and the instance
317
+ # type of the current definition.
318
+ #
319
+ # If the return value of a method definition is set to a Proc (or any
320
+ # other object that responds to `:call`) it will be called and passed the
321
+ # current instance as an argument.
322
+ #
323
+ # @todo Support for method arguments, if needed.
324
+ # @param [String] name The name of the method to call.
325
+ # @return [Mixed]
326
+ #
327
+ def call(name)
328
+ method = lookup(method_call_type, name)
329
+ return_value = nil
330
+
331
+ if method
332
+ return_value = method.return_value
333
+
334
+ if return_value.respond_to?(:call)
335
+ return_value = return_value.call(self)
336
+ end
337
+ end
338
+
339
+ return return_value
340
+ end
341
+
342
+ ##
343
+ # Returns `true` if the current definition list or one of the parents has
344
+ # the specified definition.
345
+ #
346
+ # @example
347
+ # string.has_definition?(:instance_method, 'downcase') # => true
348
+ #
349
+ # @param [#to_sym] type
350
+ # @param [String] name
351
+ # @return [TrueClass|FalseClass]
352
+ #
353
+ def has_definition?(type, name)
354
+ type, name = prepare_lookup(type, name)
355
+
356
+ if definitions[type] and definitions[type][name]
357
+ return true
358
+
359
+ elsif lookup_parent?(type)
360
+ parents.each do |parent|
361
+ return true if parent.has_definition?(type, name)
362
+ end
363
+ end
364
+
365
+ return false
366
+ end
367
+
368
+ ##
369
+ # Determines the call types for methods called on the current definition.
370
+ #
371
+ # @return [Symbol]
372
+ #
373
+ def method_call_type
374
+ return class? ? :method : :instance_method
375
+ end
376
+
377
+ ##
378
+ # @return [TrueClass|FalseClass]
379
+ #
380
+ def class?
381
+ return instance_type == :class
382
+ end
383
+
384
+ ##
385
+ # @return [TrueClass|FalseClass]
386
+ #
387
+ def instance?
388
+ return instance_type == :instance
389
+ end
390
+
391
+ ##
392
+ # Updates the definition object so that it represents an instance of a
393
+ # Ruby value.
394
+ #
395
+ def instance!
396
+ @instance_type = :instance
397
+ end
398
+
399
+ ##
400
+ # Checks if the specified definition is defined in the current object,
401
+ # ignoring data in any parent definitions.
402
+ #
403
+ # @see RubyLint::Definition::RubyObject#has_definition?
404
+ # @return [TrueClass|FalseClass]
405
+ #
406
+ def defines?(type, name)
407
+ type, name = prepare_lookup(type, name)
408
+
409
+ return definitions[type] && definitions[type][name]
410
+ end
411
+
412
+ ##
413
+ # Returns a list of all the definitions for the specific type. This list
414
+ # excludes anything defined in parent definitions.
415
+ #
416
+ # @example
417
+ # string.list(:instance_method) # => [..., ..., ...]
418
+ #
419
+ # @param [#to_sym] type
420
+ # @return [Array]
421
+ #
422
+ def list(type)
423
+ return definitions[prepare_type(type)].values
424
+ end
425
+
426
+ ##
427
+ # Returns the length of an attribute or 0.
428
+ #
429
+ # @param [#to_sym] attribute
430
+ # @return [Numeric]
431
+ #
432
+ def length_of(attribute)
433
+ value = send(attribute)
434
+
435
+ return value ? value.length : 0
436
+ end
437
+
438
+ ##
439
+ # Resets the list of definitions for the current RubyObject instance.
440
+ #
441
+ def clear!
442
+ @definitions = {
443
+ :local_variable => {},
444
+ :instance_variable => {},
445
+ :class_variable => {},
446
+ :global_variable => {},
447
+ :constant => {},
448
+ :method => {},
449
+ :instance_method => {},
450
+ :member => {},
451
+ :keyword => {}
452
+ }
453
+ end
454
+
455
+ ##
456
+ # Merges the definitions object `other` into the current one.
457
+ #
458
+ # @param [RubyLint::Definition::RubyObject] other
459
+ #
460
+ def merge(other)
461
+ other.definitions.each do |type, values|
462
+ values.each do |name, definition|
463
+ definitions[type][name] = definition
464
+ end
465
+ end
466
+ end
467
+
468
+ ##
469
+ # Copies all the definitions in `source` of type `type` into the current
470
+ # definitions object.
471
+ #
472
+ # @param [RubyLint::Definition::RubyObject] source
473
+ # @param [Symbol] source_type The type of definitions to copy from the
474
+ # source.
475
+ # @param [Symbol] target_type The type to store the definitions under,
476
+ # set to the `source_type` value by default.
477
+ #
478
+ def copy(source, source_type, target_type = source_type)
479
+ source.list(source_type).each do |definition|
480
+ add(target_type, definition.name, definition)
481
+ end
482
+ end
483
+
484
+ ##
485
+ # Returns an Array containing all the receivers of the current
486
+ # definition. These receivers are sorted from left to right. For example,
487
+ # assume the following:
488
+ #
489
+ # a.b.c
490
+ #
491
+ # In this case the return value would be as following:
492
+ #
493
+ # [a, b, c]
494
+ #
495
+ # @return [Array]
496
+ #
497
+ def receiver_path
498
+ receivers = []
499
+ source = self
500
+
501
+ while receiver = source.receiver
502
+ receivers << receiver
503
+ source = receiver
504
+ end
505
+
506
+ return receivers << self
507
+ end
508
+
509
+ ##
510
+ # Creates a new definition object based on the current one that
511
+ # represents an instance of a Ruby value (instead of a class).
512
+ #
513
+ # @param [Hash] options Attributes to override in the new definition.
514
+ # @return [RubyLint::Definition::RubyObject]
515
+ #
516
+ def instance(options = {})
517
+ options = {
518
+ :name => name,
519
+ :type => type,
520
+ :instance_type => :instance,
521
+ :value => value,
522
+ :parents => [self]
523
+ }.merge(options)
524
+
525
+ return self.class.new(options)
526
+ end
527
+
528
+ ##
529
+ # Returns `true` if the object was referenced more than once.
530
+ #
531
+ # @return [TrueClass|FalseClass]
532
+ #
533
+ def used?
534
+ return @reference_amount > 0
535
+ end
536
+
537
+ ##
538
+ # Defines a new child constant.
539
+ #
540
+ # @example
541
+ # string.define_constant('NEWLINE')
542
+ #
543
+ # @param [String] name
544
+ # @return [RubyLint::Definition::RubyObject]
545
+ #
546
+ def define_constant(name, &block)
547
+ if name.include?(PATH_SEPARATOR)
548
+ path = name.split(PATH_SEPARATOR)
549
+ target = lookup_constant_path(path[0..-2])
550
+ definition = target.define_constant(path[-1], &block)
551
+ else
552
+ definition = add_child_definition(name, :constant, &block)
553
+ end
554
+
555
+ return definition
556
+ end
557
+
558
+ ##
559
+ # Defines a new global variable in the current definition.
560
+ #
561
+ # @example
562
+ # string.define_global_variable('$name', '...')
563
+ #
564
+ # @param [String] name
565
+ # @param [Mixed] value
566
+ #
567
+ def define_global_variable(name, value = nil)
568
+ return add_child_definition(name, :global_variable, value)
569
+ end
570
+
571
+ ##
572
+ # Defines a new class method.
573
+ #
574
+ # @example
575
+ # string.define_method(:new)
576
+ #
577
+ # @param [String] name
578
+ # @return [RubyLint::Definition::RubyMethod]
579
+ #
580
+ def define_method(name, &block)
581
+ return add_child_method(name, :method, &block)
582
+ end
583
+
584
+ ##
585
+ # Defines a new instance method.
586
+ #
587
+ # @example
588
+ # string.define_instance_method(:gsub)
589
+ #
590
+ # @see RubyLint::Definition::RubyObject#define_method
591
+ #
592
+ def define_instance_method(name, &block)
593
+ return add_child_method(name, :instance_method, &block)
594
+ end
595
+
596
+ ##
597
+ # Helper method that makes it easier to provide the two constructor
598
+ # methods `new` and `initialize`. The supplied block is yielded on both
599
+ # method definitions.
600
+ #
601
+ # @example
602
+ # some_object.define_constructors do |method|
603
+ # method.argument('name')
604
+ # end
605
+ #
606
+ def define_constructors(&block)
607
+ define_method('new', &block)
608
+ define_instance_method('initialize', &block)
609
+ end
610
+
611
+ ##
612
+ # Adds the object(s) to the list of parent definitions.
613
+ #
614
+ # @param [Array] definitions
615
+ #
616
+ def inherits(*definitions)
617
+ self.parents += definitions
618
+ end
619
+
620
+ ##
621
+ # Returns a pretty formatted String that shows some info about the
622
+ # current definition.
623
+ #
624
+ # @return [String]
625
+ #
626
+ def inspect
627
+ attributes = [
628
+ %Q(@name="#{name}"),
629
+ %Q(@type="#{type}"),
630
+ %Q(@instance_type="#{instance_type}")
631
+ ]
632
+
633
+ # See <http://stackoverflow.com/a/2818916> for more info.
634
+ address = (object_id << 1).to_s(16)
635
+
636
+ return %Q(#<#{self.class}:0x#{address} #{attributes.join(' ')}>)
637
+ end
638
+
639
+ private
640
+
641
+ ##
642
+ # Updates each parent definition if it has an existing definition for hte
643
+ # given type and name.
644
+ #
645
+ # @see #add
646
+ #
647
+ def update_parent_definitions(type, name, value)
648
+ parents.each do |parent|
649
+ parent.add(type, name, value) if parent.has_definition?(type, name)
650
+ end
651
+ end
652
+
653
+ ##
654
+ # Adds a new child definition to the current definition.
655
+ #
656
+ # @param [String] name The name of the definition.
657
+ # @param [Symbol] type The definition type.
658
+ # @param [Mixed] value
659
+ # @return [RubyLint::Definition::RubyObject]
660
+ #
661
+ def add_child_definition(name, type, value = nil, &block)
662
+ definition = self.class.new(
663
+ :name => name,
664
+ :type => type,
665
+ :value => nil,
666
+ :parents => [self],
667
+ &block
668
+ )
669
+
670
+ add(definition.type, definition.name, definition)
671
+
672
+ return definition
673
+ end
674
+
675
+ ##
676
+ # Adds a new child method to the current definition.
677
+ #
678
+ # @see RubyLint::Definition::RubyObject#add_child_definition
679
+ #
680
+ def add_child_method(name, type, &block)
681
+ definition = RubyMethod.new(
682
+ :name => name,
683
+ :type => :method,
684
+ :method_type => type,
685
+ :parents => [self],
686
+ &block
687
+ )
688
+
689
+ add(definition.method_type, definition.name, definition)
690
+
691
+ return definition
692
+ end
693
+
694
+ ##
695
+ # Returns a boolean that indicates if the current definition type should
696
+ # be looked up in a parent definition.
697
+ #
698
+ # @param [Symbol] type The type of definition.
699
+ # @return [Trueclass|FalseClass]
700
+ #
701
+ def lookup_parent?(type)
702
+ return LOOKUP_PARENT.include?(type) && !parents.empty?
703
+ end
704
+
705
+ ##
706
+ # Returns a Hash containing the default options.
707
+ #
708
+ # @return [Hash]
709
+ #
710
+ def default_options
711
+ return {
712
+ :update_parents => [],
713
+ :instance_type => :class,
714
+ :parents => [],
715
+ :receiver => nil,
716
+ :reference_amount => 0,
717
+ :value => nil
718
+ }
719
+ end
720
+
721
+ ##
722
+ # Casts the type and name of data to look up to the correct values.
723
+ #
724
+ # @param [#to_sym] type
725
+ # @param [#to_s] name
726
+ # @return [Array]
727
+ #
728
+ def prepare_lookup(type, name)
729
+ return prepare_type(type), prepare_name(name)
730
+ end
731
+
732
+ ##
733
+ # Prepares the name of a definition.
734
+ #
735
+ # @param [#to_s] name
736
+ # @return [String]
737
+ #
738
+ def prepare_name(name)
739
+ name = name.to_s unless name.is_a?(String)
740
+
741
+ return name
742
+ end
743
+
744
+ ##
745
+ # Prepares the data type name.
746
+ #
747
+ # @param [#to_sym] type
748
+ # @return [Symbol]
749
+ #
750
+ def prepare_type(type)
751
+ type = type.to_sym unless type.is_a?(Symbol)
752
+
753
+ return type
754
+ end
755
+ end # RubyObject
756
+ end # Definition
757
+ end # RubyLint