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.
- data.tar.gz.asc +14 -14
- data/.gitignore +1 -2
- data/.rubocop.yml +59 -0
- data/.travis.yml +3 -7
- data/.yardopts +2 -2
- data/Gemfile +4 -0
- data/MANIFEST +103 -67
- data/README.md +13 -31
- data/Rakefile +1 -6
- data/checksum/ruby-lint-0.0.3.gem.sha512 +1 -0
- data/debug/memory_usage.rb +14 -0
- data/debug/profile.rb +18 -0
- data/doc/architecture.md +14 -18
- data/doc/changelog.md +29 -0
- data/doc/code_analysis.md +12 -12
- data/doc/configuration.md +21 -50
- data/doc/graphviz/flow.dot +1 -1
- data/doc/images/flow.png +0 -0
- data/lib/ruby-lint.rb +33 -19
- data/lib/ruby-lint/analysis/argument_amount.rb +84 -0
- data/lib/ruby-lint/analysis/base.rb +132 -0
- data/lib/ruby-lint/analysis/confusing_variables.rb +26 -0
- data/lib/ruby-lint/analysis/pedantics.rb +36 -0
- data/lib/ruby-lint/analysis/shadowing_variables.rb +47 -0
- data/lib/ruby-lint/analysis/undefined_methods.rb +91 -0
- data/lib/ruby-lint/analysis/undefined_variables.rb +46 -0
- data/lib/ruby-lint/analysis/unused_variables.rb +49 -0
- data/lib/ruby-lint/ast/builder.rb +17 -0
- data/lib/ruby-lint/ast/node.rb +39 -0
- data/lib/ruby-lint/cli.rb +0 -19
- data/lib/ruby-lint/cli/analyze.rb +54 -28
- data/lib/ruby-lint/cli/ast.rb +21 -6
- data/lib/ruby-lint/cli/base.rb +0 -23
- data/lib/ruby-lint/configuration.rb +112 -42
- data/lib/ruby-lint/constant_loader.rb +10 -28
- data/lib/ruby-lint/default_names.rb +19 -0
- data/lib/ruby-lint/definition/constant_proxy.rb +56 -0
- data/lib/ruby-lint/definition/ruby_method.rb +21 -143
- data/lib/ruby-lint/definition/ruby_object.rb +142 -246
- data/lib/ruby-lint/definition_builder/base.rb +43 -0
- data/lib/ruby-lint/definition_builder/primitive.rb +39 -0
- data/lib/ruby-lint/definition_builder/ruby_array.rb +77 -0
- data/lib/ruby-lint/definition_builder/ruby_block.rb +34 -0
- data/lib/ruby-lint/definition_builder/ruby_class.rb +24 -0
- data/lib/ruby-lint/definition_builder/ruby_hash.rb +37 -0
- data/lib/ruby-lint/definition_builder/ruby_method.rb +84 -0
- data/lib/ruby-lint/definition_builder/ruby_module.rb +68 -0
- data/lib/ruby-lint/definition_generator.rb +41 -15
- data/lib/ruby-lint/definitions/core/arg0.rb +1 -1
- data/lib/ruby-lint/definitions/core/argf.rb +1 -1
- data/lib/ruby-lint/definitions/core/argument_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/argv.rb +1 -1
- data/lib/ruby-lint/definitions/core/array.rb +6 -6
- data/lib/ruby-lint/definitions/core/autoload.rb +2 -2
- data/lib/ruby-lint/definitions/core/basic_object.rb +3 -3
- data/lib/ruby-lint/definitions/core/bignum.rb +2 -2
- data/lib/ruby-lint/definitions/core/binding.rb +2 -2
- data/lib/ruby-lint/definitions/core/class.rb +2 -2
- data/lib/ruby-lint/definitions/core/comparable.rb +1 -1
- data/lib/ruby-lint/definitions/core/complex.rb +4 -4
- data/lib/ruby-lint/definitions/core/condition_variable.rb +2 -2
- data/lib/ruby-lint/definitions/core/continuation.rb +2 -2
- data/lib/ruby-lint/definitions/core/data.rb +2 -2
- data/lib/ruby-lint/definitions/core/date.rb +34 -34
- data/lib/ruby-lint/definitions/core/date_time.rb +26 -26
- data/lib/ruby-lint/definitions/core/default_record_separator.rb +1 -1
- data/lib/ruby-lint/definitions/core/digest.rb +14 -14
- data/lib/ruby-lint/definitions/core/dir.rb +34 -34
- data/lib/ruby-lint/definitions/core/encoding.rb +237 -237
- data/lib/ruby-lint/definitions/core/encoding_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/enumerable.rb +15 -15
- data/lib/ruby-lint/definitions/core/enumerator.rb +2 -2
- data/lib/ruby-lint/definitions/core/env.rb +1 -1
- data/lib/ruby-lint/definitions/core/eoferror.rb +2 -2
- data/lib/ruby-lint/definitions/core/erb.rb +22 -22
- data/lib/ruby-lint/definitions/core/errno.rb +525 -525
- data/lib/ruby-lint/definitions/core/etc.rb +6 -6
- data/lib/ruby-lint/definitions/core/exception.rb +2 -2
- data/lib/ruby-lint/definitions/core/false.rb +1 -1
- data/lib/ruby-lint/definitions/core/false_class.rb +2 -2
- data/lib/ruby-lint/definitions/core/fatal_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/fiber.rb +2 -2
- data/lib/ruby-lint/definitions/core/fiber_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/file.rb +68 -68
- data/lib/ruby-lint/definitions/core/file_list.rb +2 -2
- data/lib/ruby-lint/definitions/core/file_test.rb +1 -1
- data/lib/ruby-lint/definitions/core/file_utils.rb +16 -16
- data/lib/ruby-lint/definitions/core/fixnum.rb +4 -4
- data/lib/ruby-lint/definitions/core/float.rb +16 -16
- data/lib/ruby-lint/definitions/core/float_domain_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/gc.rb +2 -2
- data/lib/ruby-lint/definitions/core/gem.rb +119 -119
- data/lib/ruby-lint/definitions/core/hash.rb +14 -14
- data/lib/ruby-lint/definitions/core/immediate_value.rb +1 -1
- data/lib/ruby-lint/definitions/core/index_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/integer.rb +2 -2
- data/lib/ruby-lint/definitions/core/interrupt.rb +2 -2
- data/lib/ruby-lint/definitions/core/io.rb +38 -38
- data/lib/ruby-lint/definitions/core/ioerror.rb +2 -2
- data/lib/ruby-lint/definitions/core/kernel.rb +3 -3
- data/lib/ruby-lint/definitions/core/key_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/load_error.rb +6 -6
- data/lib/ruby-lint/definitions/core/local_jump_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/main.rb +1 -1
- data/lib/ruby-lint/definitions/core/marshal.rb +35 -35
- data/lib/ruby-lint/definitions/core/match_data.rb +2 -2
- data/lib/ruby-lint/definitions/core/math.rb +7 -7
- data/lib/ruby-lint/definitions/core/memory_segmention_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/method.rb +2 -2
- data/lib/ruby-lint/definitions/core/module.rb +1 -1
- data/lib/ruby-lint/definitions/core/monitor.rb +4 -4
- data/lib/ruby-lint/definitions/core/monitor_mixin.rb +5 -5
- data/lib/ruby-lint/definitions/core/mutex.rb +2 -2
- data/lib/ruby-lint/definitions/core/name_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/nil.rb +1 -1
- data/lib/ruby-lint/definitions/core/nil_class.rb +2 -2
- data/lib/ruby-lint/definitions/core/no_memory_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/no_method_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/not_implemented_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/numeric.rb +2 -2
- data/lib/ruby-lint/definitions/core/object.rb +2 -2
- data/lib/ruby-lint/definitions/core/object_space.rb +1 -1
- data/lib/ruby-lint/definitions/core/open_struct.rb +3 -3
- data/lib/ruby-lint/definitions/core/option_parser.rb +83 -83
- data/lib/ruby-lint/definitions/core/precision.rb +1 -1
- data/lib/ruby-lint/definitions/core/primitive_failure.rb +2 -2
- data/lib/ruby-lint/definitions/core/proc.rb +2 -2
- data/lib/ruby-lint/definitions/core/process.rb +29 -29
- data/lib/ruby-lint/definitions/core/psych.rb +149 -149
- data/lib/ruby-lint/definitions/core/queue.rb +2 -2
- data/lib/ruby-lint/definitions/core/rake.rb +117 -117
- data/lib/ruby-lint/definitions/core/rake_file_utils.rb +1 -1
- data/lib/ruby-lint/definitions/core/rakeversion.rb +1 -1
- data/lib/ruby-lint/definitions/core/random.rb +2 -2
- data/lib/ruby-lint/definitions/core/range.rb +4 -4
- data/lib/ruby-lint/definitions/core/range_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/rational.rb +2 -2
- data/lib/ruby-lint/definitions/core/rb_config.rb +3 -3
- data/lib/ruby-lint/definitions/core/regexp.rb +28 -28
- data/lib/ruby-lint/definitions/core/regexp_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/rubinius.rb +1057 -1057
- data/lib/ruby-lint/definitions/core/ruby_copyright.rb +1 -1
- data/lib/ruby-lint/definitions/core/ruby_description.rb +1 -1
- data/lib/ruby-lint/definitions/core/ruby_engine.rb +1 -1
- data/lib/ruby-lint/definitions/core/ruby_lint.rb +9 -9
- data/lib/ruby-lint/definitions/core/ruby_patchlevel.rb +1 -1
- data/lib/ruby-lint/definitions/core/ruby_platform.rb +1 -1
- data/lib/ruby-lint/definitions/core/ruby_release_date.rb +1 -1
- data/lib/ruby-lint/definitions/core/ruby_version.rb +1 -1
- data/lib/ruby-lint/definitions/core/runtime_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/scan_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/script_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/security_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/shellwords.rb +1 -1
- data/lib/ruby-lint/definitions/core/signal.rb +3 -3
- data/lib/ruby-lint/definitions/core/signal_exception.rb +2 -2
- data/lib/ruby-lint/definitions/core/singleton.rb +2 -2
- data/lib/ruby-lint/definitions/core/sized_queue.rb +2 -2
- data/lib/ruby-lint/definitions/core/standard_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/stderr.rb +1 -1
- data/lib/ruby-lint/definitions/core/stdin.rb +1 -1
- data/lib/ruby-lint/definitions/core/stdout.rb +1 -1
- data/lib/ruby-lint/definitions/core/stop_iteration.rb +2 -2
- data/lib/ruby-lint/definitions/core/string.rb +21 -21
- data/lib/ruby-lint/definitions/core/string_io.rb +7 -7
- data/lib/ruby-lint/definitions/core/string_scanner.rb +4 -4
- data/lib/ruby-lint/definitions/core/struct.rb +20 -20
- data/lib/ruby-lint/definitions/core/syck.rb +4 -4
- data/lib/ruby-lint/definitions/core/symbol.rb +2 -2
- data/lib/ruby-lint/definitions/core/syntax_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/system_call_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/system_exit.rb +2 -2
- data/lib/ruby-lint/definitions/core/system_stack_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/thread.rb +6 -6
- data/lib/ruby-lint/definitions/core/thread_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/thread_group.rb +2 -2
- data/lib/ruby-lint/definitions/core/time.rb +3 -3
- data/lib/ruby-lint/definitions/core/toplevel_binding.rb +1 -1
- data/lib/ruby-lint/definitions/core/true.rb +1 -1
- data/lib/ruby-lint/definitions/core/true_class.rb +2 -2
- data/lib/ruby-lint/definitions/core/type_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/unbound_method.rb +2 -2
- data/lib/ruby-lint/definitions/core/unmarshalable.rb +1 -1
- data/lib/ruby-lint/definitions/core/unsupported_library_error.rb +2 -2
- data/lib/ruby-lint/definitions/core/weak_ref.rb +4 -4
- data/lib/ruby-lint/definitions/core/zero_division_error.rb +2 -2
- data/lib/ruby-lint/definitions/rails.rb +12 -0
- data/lib/ruby-lint/definitions/rails/abstract_controller.rb +335 -0
- data/lib/ruby-lint/definitions/rails/action_controller.rb +1244 -0
- data/lib/ruby-lint/definitions/rails/action_dispatch.rb +741 -0
- data/lib/ruby-lint/definitions/rails/action_mailer.rb +502 -0
- data/lib/ruby-lint/definitions/rails/action_pack.rb +16 -0
- data/lib/ruby-lint/definitions/rails/action_view.rb +898 -0
- data/lib/ruby-lint/definitions/rails/active_model.rb +437 -0
- data/lib/ruby-lint/definitions/rails/active_record.rb +2901 -0
- data/lib/ruby-lint/definitions/rails/active_support.rb +1963 -0
- data/lib/ruby-lint/definitions/rails/arel.rb +665 -0
- data/lib/ruby-lint/definitions/rails/rails.rb +452 -0
- data/lib/ruby-lint/definitions/rails/sprockets.rb +968 -0
- data/lib/ruby-lint/generated_constant.rb +33 -0
- data/lib/ruby-lint/helper/constant_paths.rb +30 -21
- data/lib/ruby-lint/inspector.rb +20 -2
- data/lib/ruby-lint/iterator.rb +11 -171
- data/lib/ruby-lint/nested_stack.rb +46 -0
- data/lib/ruby-lint/parser.rb +24 -806
- data/lib/ruby-lint/report.rb +2 -30
- data/lib/ruby-lint/report/entry.rb +2 -2
- data/lib/ruby-lint/runner.rb +81 -0
- data/lib/ruby-lint/template/definition.erb +12 -8
- data/lib/ruby-lint/variable_predicates.rb +16 -58
- data/lib/ruby-lint/version.rb +1 -1
- data/lib/ruby-lint/virtual_machine.rb +1044 -0
- data/ruby-lint.gemspec +17 -7
- data/spec/fixtures/complex/rails/basic_controller.rb +9 -0
- data/spec/fixtures/complex/rcap.rb +38 -0
- data/spec/fixtures/complex/slop.rb +680 -0
- data/spec/fixtures/config.yml +8 -0
- data/spec/fixtures/invalid.rb +3 -0
- data/spec/fixtures/invalid_2.rb +3 -0
- data/spec/fixtures/syntax_error.rb +1 -0
- data/spec/fixtures/valid.rb +3 -0
- data/spec/helper.rb +6 -0
- data/spec/ruby-lint/{analyze → analysis}/argument_amount.rb +7 -7
- data/spec/ruby-lint/analysis/confusing_variables.rb +46 -0
- data/spec/ruby-lint/analysis/pedantics.rb +43 -0
- data/spec/ruby-lint/{analyze → analysis}/shadowing_variables.rb +5 -5
- data/spec/ruby-lint/{analyze → analysis}/undefined_methods.rb +18 -18
- data/spec/ruby-lint/{analyze → analysis}/undefined_variables.rb +19 -25
- data/spec/ruby-lint/{analyze → analysis}/unused_variables.rb +29 -16
- data/spec/ruby-lint/ast/node.rb +33 -0
- data/spec/ruby-lint/cli/analyze.rb +31 -0
- data/spec/ruby-lint/cli/ast.rb +23 -0
- data/spec/ruby-lint/configuration.rb +45 -6
- data/spec/ruby-lint/definition/constant_proxy.rb +31 -0
- data/spec/ruby-lint/definition/dsl.rb +13 -20
- data/spec/ruby-lint/definition/ruby_method.rb +65 -148
- data/spec/ruby-lint/definition/ruby_object.rb +60 -96
- data/spec/ruby-lint/definition_builder/primitive.rb +62 -0
- data/spec/ruby-lint/definition_builder/ruby_class.rb +108 -0
- data/spec/ruby-lint/definition_builder/ruby_method.rb +53 -0
- data/spec/ruby-lint/definition_builder/ruby_module.rb +50 -0
- data/spec/ruby-lint/iterator.rb +40 -16
- data/spec/ruby-lint/nested_stack.rb +23 -0
- data/spec/ruby-lint/parser.rb +14 -0
- data/spec/ruby-lint/report.rb +0 -10
- data/spec/ruby-lint/report/entry.rb +8 -4
- data/spec/ruby-lint/runner.rb +32 -0
- data/spec/ruby-lint/virtual_machine/assignments/arrays.rb +87 -0
- data/spec/ruby-lint/virtual_machine/assignments/hashes.rb +52 -0
- data/spec/ruby-lint/virtual_machine/assignments/optional.rb +41 -0
- data/spec/ruby-lint/{definitions_builder → virtual_machine}/assignments/return_values.rb +11 -11
- data/spec/ruby-lint/virtual_machine/assignments/variables.rb +85 -0
- data/spec/ruby-lint/virtual_machine/associate_nodes.rb +17 -0
- data/spec/ruby-lint/virtual_machine/autoloading.rb +31 -0
- data/spec/ruby-lint/virtual_machine/blocks.rb +64 -0
- data/spec/ruby-lint/virtual_machine/classes/class_methods.rb +21 -0
- data/spec/ruby-lint/virtual_machine/classes/extending.rb +104 -0
- data/spec/ruby-lint/virtual_machine/classes/redefining.rb +24 -0
- data/spec/ruby-lint/virtual_machine/classes/sclass.rb +94 -0
- data/spec/ruby-lint/virtual_machine/classes/scoping.rb +60 -0
- data/spec/ruby-lint/virtual_machine/complex/rails.rb +18 -0
- data/spec/ruby-lint/virtual_machine/complex/rcap.rb +15 -0
- data/spec/ruby-lint/virtual_machine/complex/slop.rb +16 -0
- data/spec/ruby-lint/{definitions_builder → virtual_machine}/for.rb +2 -2
- data/spec/ruby-lint/virtual_machine/freeze.rb +13 -0
- data/spec/ruby-lint/virtual_machine/interpolation.rb +12 -0
- data/spec/ruby-lint/virtual_machine/methods/defining.rb +40 -0
- data/spec/ruby-lint/virtual_machine/methods/exporting.rb +19 -0
- data/spec/ruby-lint/virtual_machine/methods/parameters.rb +77 -0
- data/spec/ruby-lint/virtual_machine/methods/patching.rb +26 -0
- data/spec/ruby-lint/virtual_machine/methods/scoping.rb +63 -0
- data/spec/ruby-lint/virtual_machine/methods/visibility.rb +64 -0
- data/spec/ruby-lint/{definitions_builder → virtual_machine}/modules.rb +16 -16
- data/spec/ruby-lint/virtual_machine/reference_amount.rb +33 -0
- data/spec/ruby-lint/virtual_machine/unused.rb +17 -0
- data/spec/support/bacon.rb +13 -13
- data/spec/support/building.rb +23 -16
- data/spec/support/coveralls.rb +5 -0
- data/spec/support/fixtures.rb +20 -0
- data/spec/support/parsing.rb +3 -5
- data/spec/support/simplecov.rb +5 -3
- data/task/build.rake +1 -1
- data/task/cop.rake +11 -0
- data/task/generate.rake +40 -2
- data/task/profile.rake +27 -0
- data/task/todo.rake +6 -0
- data/task/travis.rake +7 -0
- metadata +160 -75
- metadata.gz.asc +14 -14
- data/doc/build/.gitkeep +0 -0
- data/lib/ruby-lint/analyze/argument_amount.rb +0 -73
- data/lib/ruby-lint/analyze/shadowing_variables.rb +0 -32
- data/lib/ruby-lint/analyze/undefined_methods.rb +0 -68
- data/lib/ruby-lint/analyze/undefined_variables.rb +0 -72
- data/lib/ruby-lint/analyze/unused_variables.rb +0 -48
- data/lib/ruby-lint/base.rb +0 -85
- data/lib/ruby-lint/definitions_builder.rb +0 -692
- data/lib/ruby-lint/helper/conversion.rb +0 -33
- data/lib/ruby-lint/helper/current_scope.rb +0 -98
- data/lib/ruby-lint/helper/methods.rb +0 -91
- data/lib/ruby-lint/node.rb +0 -107
- data/lib/ruby-lint/parser_error.rb +0 -30
- data/spec/ruby-lint/constant_loader.rb +0 -32
- data/spec/ruby-lint/definition/method_calls.rb +0 -26
- data/spec/ruby-lint/definitions_builder/assignments/arrays.rb +0 -71
- data/spec/ruby-lint/definitions_builder/assignments/hashes.rb +0 -65
- data/spec/ruby-lint/definitions_builder/assignments/objects.rb +0 -23
- data/spec/ruby-lint/definitions_builder/assignments/optional.rb +0 -22
- data/spec/ruby-lint/definitions_builder/assignments/variables.rb +0 -71
- data/spec/ruby-lint/definitions_builder/associate_nodes.rb +0 -17
- data/spec/ruby-lint/definitions_builder/blocks.rb +0 -40
- data/spec/ruby-lint/definitions_builder/classes.rb +0 -230
- data/spec/ruby-lint/definitions_builder/methods.rb +0 -147
- data/spec/ruby-lint/definitions_builder/reference_amount.rb +0 -31
- data/spec/ruby-lint/definitions_builder/unused.rb +0 -15
- data/spec/ruby-lint/node.rb +0 -38
- data/spec/ruby-lint/parser/assignments.rb +0 -225
- data/spec/ruby-lint/parser/classes.rb +0 -110
- data/spec/ruby-lint/parser/errors.rb +0 -12
- data/spec/ruby-lint/parser/metadata.rb +0 -17
- data/spec/ruby-lint/parser/method_definitions.rb +0 -111
- data/spec/ruby-lint/parser/methods.rb +0 -217
- data/spec/ruby-lint/parser/modules.rb +0 -70
- data/spec/ruby-lint/parser/operators.rb +0 -40
- data/spec/ruby-lint/parser/statements/begin.rb +0 -55
- data/spec/ruby-lint/parser/statements/case.rb +0 -34
- data/spec/ruby-lint/parser/statements/defined.rb +0 -11
- data/spec/ruby-lint/parser/statements/for.rb +0 -34
- data/spec/ruby-lint/parser/statements/if.rb +0 -46
- data/spec/ruby-lint/parser/statements/return.rb +0 -14
- data/spec/ruby-lint/parser/statements/super.rb +0 -49
- data/spec/ruby-lint/parser/statements/unless.rb +0 -42
- data/spec/ruby-lint/parser/statements/until.rb +0 -25
- data/spec/ruby-lint/parser/statements/while.rb +0 -25
- data/spec/ruby-lint/parser/statements/yield.rb +0 -18
- data/spec/ruby-lint/parser/types/arrays.rb +0 -47
- data/spec/ruby-lint/parser/types/booleans.rb +0 -11
- data/spec/ruby-lint/parser/types/constants.rb +0 -32
- data/spec/ruby-lint/parser/types/hashes.rb +0 -55
- data/spec/ruby-lint/parser/types/nil.rb +0 -7
- data/spec/ruby-lint/parser/types/numbers.rb +0 -11
- data/spec/ruby-lint/parser/types/procs.rb +0 -11
- data/spec/ruby-lint/parser/types/ranges.rb +0 -11
- data/spec/ruby-lint/parser/types/regexp.rb +0 -27
- data/spec/ruby-lint/parser/types/strings.rb +0 -44
- data/spec/ruby-lint/parser/types/symbols.rb +0 -15
- data/task/stdlib.rake +0 -23
data/lib/ruby-lint/report.rb
CHANGED
|
@@ -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 =
|
|
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
|
|
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.
|
|
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
|
-
#
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
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[:
|
|
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 = [:
|
|
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
|
-
:
|
|
53
|
-
:
|
|
54
|
-
:
|
|
55
|
-
:float
|
|
56
|
-
:regexp
|
|
57
|
-
:array
|
|
58
|
-
:hash
|
|
59
|
-
:
|
|
60
|
-
:
|
|
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
|
-
|
|
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
|
|
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
|
|
99
|
-
return
|
|
56
|
+
def constant_path?
|
|
57
|
+
return constant? && children[0].constant?
|
|
100
58
|
end
|
|
101
59
|
|
|
102
60
|
##
|
data/lib/ruby-lint/version.rb
CHANGED
|
@@ -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
|