ruby-lint 0.0.5 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.asc +14 -14
- data/.gitignore +1 -0
- data/.yardopts +1 -1
- data/Gemfile +3 -3
- data/MANIFEST +16 -3
- data/benchmark/virtual_machine.rb +17 -0
- data/checksum/ruby-lint-0.0.5.gem.sha512 +1 -0
- data/doc/changelog.md +42 -0
- data/doc/configuration.md +133 -13
- data/lib/ruby-lint/analysis/shadowing_variables.rb +8 -14
- data/lib/ruby-lint/analysis/unused_variables.rb +17 -0
- data/lib/ruby-lint/ast/node.rb +18 -3
- data/lib/ruby-lint/cache.rb +121 -0
- data/lib/ruby-lint/cache_entry.rb +44 -0
- data/lib/ruby-lint/cli/analyze.rb +37 -18
- data/lib/ruby-lint/cli/plot.rb +94 -0
- data/lib/ruby-lint/cli.rb +1 -0
- data/lib/ruby-lint/configuration.rb +48 -3
- data/lib/ruby-lint/definition/ruby_method.rb +28 -1
- data/lib/ruby-lint/definition/ruby_object.rb +37 -3
- data/lib/ruby-lint/definition_builder/ruby_method.rb +4 -1
- data/lib/ruby-lint/definition_builder/ruby_module.rb +4 -1
- data/lib/ruby-lint/definition_generator.rb +3 -2
- data/lib/ruby-lint/definitions/core/arg0.rb +3 -1
- data/lib/ruby-lint/definitions/core/argf.rb +3 -1
- data/lib/ruby-lint/definitions/core/argument_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/argv.rb +3 -1
- data/lib/ruby-lint/definitions/core/array.rb +3 -1
- data/lib/ruby-lint/definitions/core/autoload.rb +3 -1
- data/lib/ruby-lint/definitions/core/basic_object.rb +2 -0
- data/lib/ruby-lint/definitions/core/bignum.rb +3 -1
- data/lib/ruby-lint/definitions/core/binding.rb +3 -1
- data/lib/ruby-lint/definitions/core/class.rb +2 -0
- data/lib/ruby-lint/definitions/core/comparable.rb +3 -1
- data/lib/ruby-lint/definitions/core/complex.rb +3 -1
- data/lib/ruby-lint/definitions/core/condition_variable.rb +3 -1
- data/lib/ruby-lint/definitions/core/continuation.rb +3 -1
- data/lib/ruby-lint/definitions/core/data.rb +3 -1
- data/lib/ruby-lint/definitions/core/date.rb +3 -1
- data/lib/ruby-lint/definitions/core/date_time.rb +3 -1
- data/lib/ruby-lint/definitions/core/default_record_separator.rb +3 -1
- data/lib/ruby-lint/definitions/core/digest.rb +3 -1
- data/lib/ruby-lint/definitions/core/dir.rb +3 -1
- data/lib/ruby-lint/definitions/core/encoding.rb +3 -1
- data/lib/ruby-lint/definitions/core/encoding_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/enumerable.rb +3 -1
- data/lib/ruby-lint/definitions/core/enumerator.rb +3 -1
- data/lib/ruby-lint/definitions/core/env.rb +4 -1
- data/lib/ruby-lint/definitions/core/eoferror.rb +3 -1
- data/lib/ruby-lint/definitions/core/erb.rb +2 -0
- data/lib/ruby-lint/definitions/core/errno.rb +3 -1
- data/lib/ruby-lint/definitions/core/etc.rb +3 -1
- data/lib/ruby-lint/definitions/core/exception.rb +3 -1
- data/lib/ruby-lint/definitions/core/false.rb +3 -1
- data/lib/ruby-lint/definitions/core/false_class.rb +3 -1
- data/lib/ruby-lint/definitions/core/fatal_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/fiber.rb +3 -1
- data/lib/ruby-lint/definitions/core/fiber_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/file.rb +3 -1
- data/lib/ruby-lint/definitions/core/file_list.rb +3 -1
- data/lib/ruby-lint/definitions/core/file_test.rb +3 -1
- data/lib/ruby-lint/definitions/core/file_utils.rb +3 -1
- data/lib/ruby-lint/definitions/core/fixnum.rb +3 -1
- data/lib/ruby-lint/definitions/core/float.rb +3 -1
- data/lib/ruby-lint/definitions/core/float_domain_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/gc.rb +3 -1
- data/lib/ruby-lint/definitions/core/gem.rb +3 -1
- data/lib/ruby-lint/definitions/core/hash.rb +3 -1
- data/lib/ruby-lint/definitions/core/immediate_value.rb +3 -1
- data/lib/ruby-lint/definitions/core/index_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/integer.rb +3 -1
- data/lib/ruby-lint/definitions/core/interrupt.rb +3 -1
- data/lib/ruby-lint/definitions/core/io.rb +3 -1
- data/lib/ruby-lint/definitions/core/ioerror.rb +3 -1
- data/lib/ruby-lint/definitions/core/kernel.rb +2 -0
- data/lib/ruby-lint/definitions/core/key_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/load_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/local_jump_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/marshal.rb +3 -1
- data/lib/ruby-lint/definitions/core/match_data.rb +3 -1
- data/lib/ruby-lint/definitions/core/math.rb +3 -1
- data/lib/ruby-lint/definitions/core/memory_segmention_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/method.rb +3 -1
- data/lib/ruby-lint/definitions/core/module.rb +2 -0
- data/lib/ruby-lint/definitions/core/monitor.rb +3 -1
- data/lib/ruby-lint/definitions/core/monitor_mixin.rb +3 -1
- data/lib/ruby-lint/definitions/core/mutex.rb +3 -1
- data/lib/ruby-lint/definitions/core/name_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/nil.rb +3 -1
- data/lib/ruby-lint/definitions/core/nil_class.rb +3 -1
- data/lib/ruby-lint/definitions/core/no_memory_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/no_method_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/not_implemented_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/numeric.rb +3 -1
- data/lib/ruby-lint/definitions/core/object.rb +3 -1
- data/lib/ruby-lint/definitions/core/object_space.rb +3 -1
- data/lib/ruby-lint/definitions/core/open_struct.rb +3 -1
- data/lib/ruby-lint/definitions/core/option_parser.rb +3 -1
- data/lib/ruby-lint/definitions/core/precision.rb +3 -1
- data/lib/ruby-lint/definitions/core/primitive_failure.rb +3 -1
- data/lib/ruby-lint/definitions/core/proc.rb +3 -1
- data/lib/ruby-lint/definitions/core/process.rb +3 -1
- data/lib/ruby-lint/definitions/core/queue.rb +3 -1
- data/lib/ruby-lint/definitions/core/rake.rb +3 -1
- data/lib/ruby-lint/definitions/core/rake_file_utils.rb +3 -1
- data/lib/ruby-lint/definitions/core/rakeversion.rb +3 -1
- data/lib/ruby-lint/definitions/core/random.rb +3 -1
- data/lib/ruby-lint/definitions/core/range.rb +3 -1
- data/lib/ruby-lint/definitions/core/range_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/rational.rb +3 -1
- data/lib/ruby-lint/definitions/core/rb_config.rb +3 -1
- data/lib/ruby-lint/definitions/core/regexp.rb +3 -1
- data/lib/ruby-lint/definitions/core/regexp_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/ruby_copyright.rb +3 -1
- data/lib/ruby-lint/definitions/core/ruby_description.rb +3 -1
- data/lib/ruby-lint/definitions/core/ruby_engine.rb +3 -1
- data/lib/ruby-lint/definitions/core/ruby_patchlevel.rb +3 -1
- data/lib/ruby-lint/definitions/core/ruby_platform.rb +3 -1
- data/lib/ruby-lint/definitions/core/ruby_release_date.rb +3 -1
- data/lib/ruby-lint/definitions/core/ruby_version.rb +3 -1
- data/lib/ruby-lint/definitions/core/runtime_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/scan_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/script_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/security_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/shellwords.rb +3 -1
- data/lib/ruby-lint/definitions/core/signal.rb +3 -1
- data/lib/ruby-lint/definitions/core/signal_exception.rb +3 -1
- data/lib/ruby-lint/definitions/core/singleton.rb +3 -1
- data/lib/ruby-lint/definitions/core/sized_queue.rb +3 -1
- data/lib/ruby-lint/definitions/core/standard_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/stderr.rb +2 -0
- data/lib/ruby-lint/definitions/core/stdin.rb +2 -0
- data/lib/ruby-lint/definitions/core/stdout.rb +2 -0
- data/lib/ruby-lint/definitions/core/stop_iteration.rb +3 -1
- data/lib/ruby-lint/definitions/core/string.rb +3 -1
- data/lib/ruby-lint/definitions/core/string_io.rb +3 -1
- data/lib/ruby-lint/definitions/core/string_scanner.rb +3 -1
- data/lib/ruby-lint/definitions/core/struct.rb +3 -1
- data/lib/ruby-lint/definitions/core/syck.rb +3 -1
- data/lib/ruby-lint/definitions/core/symbol.rb +3 -1
- data/lib/ruby-lint/definitions/core/syntax_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/system_call_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/system_exit.rb +3 -1
- data/lib/ruby-lint/definitions/core/system_stack_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/thread.rb +3 -1
- data/lib/ruby-lint/definitions/core/thread_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/thread_group.rb +3 -1
- data/lib/ruby-lint/definitions/core/time.rb +3 -1
- data/lib/ruby-lint/definitions/core/toplevel_binding.rb +3 -1
- data/lib/ruby-lint/definitions/core/true.rb +3 -1
- data/lib/ruby-lint/definitions/core/true_class.rb +3 -1
- data/lib/ruby-lint/definitions/core/type_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/unbound_method.rb +3 -1
- data/lib/ruby-lint/definitions/core/unmarshalable.rb +3 -1
- data/lib/ruby-lint/definitions/core/unsupported_library_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/weak_ref.rb +3 -1
- data/lib/ruby-lint/definitions/core/yaml.rb +1 -0
- data/lib/ruby-lint/definitions/core/zero_division_error.rb +3 -1
- data/lib/ruby-lint/definitions/core/zlib.rb +8840 -0
- data/lib/ruby-lint/definitions/rails/abstract_controller.rb +1 -0
- data/lib/ruby-lint/definitions/rails/action_controller.rb +1 -0
- data/lib/ruby-lint/definitions/rails/action_dispatch.rb +1 -0
- data/lib/ruby-lint/definitions/rails/action_mailer.rb +1 -0
- data/lib/ruby-lint/definitions/rails/action_pack.rb +1 -0
- data/lib/ruby-lint/definitions/rails/action_view.rb +1 -0
- data/lib/ruby-lint/definitions/rails/active_model.rb +1 -0
- data/lib/ruby-lint/definitions/rails/active_record.rb +1 -0
- data/lib/ruby-lint/definitions/rails/active_support.rb +1 -0
- data/lib/ruby-lint/definitions/rails/arel.rb +1 -0
- data/lib/ruby-lint/definitions/rails/rails.rb +1 -0
- data/lib/ruby-lint/definitions/rails/sprockets.rb +1 -0
- data/lib/ruby-lint/file_scanner.rb +2 -0
- data/lib/ruby-lint/iterator.rb +21 -12
- data/lib/ruby-lint/method_call_info.rb +31 -0
- data/lib/ruby-lint/node_hash.rb +105 -0
- data/lib/ruby-lint/parser.rb +4 -2
- data/lib/ruby-lint/runner.rb +62 -6
- data/lib/ruby-lint/template/definition.erb +2 -0
- data/lib/ruby-lint/version.rb +1 -1
- data/lib/ruby-lint/virtual_machine.rb +75 -43
- data/lib/ruby-lint.rb +20 -2
- data/profiling/virtual_machine.rb +20 -0
- data/ruby-lint.gemspec +2 -1
- data/spec/fixtures/complex/rcap.rb +29 -0
- data/spec/fixtures/complex/slop.rb +21 -0
- data/spec/fixtures/file_scanner/lib/ruby-lint/definition/constant_proxy.rb +6 -0
- data/spec/fixtures/file_scanner/lib/ruby-lint/global_scope.rb +6 -0
- data/spec/ruby-lint/analysis/unused_variables_spec.rb +114 -0
- data/spec/ruby-lint/cache_entry_spec.rb +25 -0
- data/spec/ruby-lint/cache_spec.rb +53 -0
- data/spec/ruby-lint/definition/ruby_method_spec.rb +4 -4
- data/spec/ruby-lint/definition/ruby_object_spec.rb +33 -0
- data/spec/ruby-lint/iterator_spec.rb +15 -0
- data/spec/ruby-lint/node_hash_spec.rb +56 -0
- data/spec/ruby-lint/runner_spec.rb +6 -1
- data/spec/ruby-lint/virtual_machine/assignments/variables_spec.rb +2 -2
- data/spec/ruby-lint/virtual_machine/location_spec.rb +64 -0
- data/spec/ruby-lint/virtual_machine/method_call_tracking_spec.rb +64 -0
- data/spec/spec_helper.rb +7 -0
- data/task/generate.rake +1 -1
- data.tar.gz.asc +14 -14
- metadata +34 -7
- metadata.gz.asc +14 -14
- data/debug/memory_usage.rb +0 -14
- data/debug/profile.rb +0 -18
- data/task/profile.rake +0 -27
@@ -11793,3 +11793,4 @@ RubyLint::GlobalScope.definitions.define_constant('ActiveRecord::WrappedDatabase
|
|
11793
11793
|
end
|
11794
11794
|
end
|
11795
11795
|
|
11796
|
+
RubyLint::GlobalScope.definitions.lookup(:const, 'ActiveRecord').deep_freeze
|
data/lib/ruby-lint/iterator.rb
CHANGED
@@ -50,7 +50,13 @@ module RubyLint
|
|
50
50
|
# the specified node (`throw` calls bubble up regardless of `catch` calls,
|
51
51
|
# unlike when using `begin/rescue`).
|
52
52
|
#
|
53
|
+
# @!attribute [r] arity_cache Hash containing the amount of arguments for
|
54
|
+
# each method.
|
55
|
+
# @return [Hash]
|
56
|
+
#
|
53
57
|
class Iterator
|
58
|
+
attr_reader :arity_cache
|
59
|
+
|
54
60
|
##
|
55
61
|
# @param [Hash] options Hash containing custom options to set for the
|
56
62
|
# iterator.
|
@@ -61,6 +67,8 @@ module RubyLint
|
|
61
67
|
end
|
62
68
|
|
63
69
|
after_initialize if respond_to?(:after_initialize)
|
70
|
+
|
71
|
+
@arity_cache = {}
|
64
72
|
end
|
65
73
|
|
66
74
|
##
|
@@ -72,8 +80,9 @@ module RubyLint
|
|
72
80
|
def iterate(node)
|
73
81
|
return unless node.is_a?(AST::Node)
|
74
82
|
|
75
|
-
before
|
76
|
-
|
83
|
+
before = :"on_#{node.type}"
|
84
|
+
after = :"after_#{node.type}"
|
85
|
+
skip_node = catch :skip_child_nodes do
|
77
86
|
execute_callback(before, node)
|
78
87
|
end
|
79
88
|
|
@@ -104,17 +113,17 @@ module RubyLint
|
|
104
113
|
# @param [Array] args Arguments to pass to the callback method.
|
105
114
|
#
|
106
115
|
def execute_callback(name, *args)
|
107
|
-
|
108
|
-
end
|
116
|
+
return unless respond_to?(name)
|
109
117
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
+
unless arity_cache.key?(name)
|
119
|
+
arity_cache[name] = method(name).arity
|
120
|
+
end
|
121
|
+
|
122
|
+
if arity_cache[name] == 0
|
123
|
+
send(name)
|
124
|
+
else
|
125
|
+
send(name, *args)
|
126
|
+
end
|
118
127
|
end
|
119
128
|
end # Iterator
|
120
129
|
end # RubyLint
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RubyLint
|
2
|
+
##
|
3
|
+
# The MethodCallInfo class stores basic information about method calls such
|
4
|
+
# as the definition of the method and location information of the method
|
5
|
+
# call.
|
6
|
+
#
|
7
|
+
# @!attribute [r] definition
|
8
|
+
# @return [RubyLint::Definition::RubyMethod]
|
9
|
+
#
|
10
|
+
# @!attribute [r] line
|
11
|
+
# @return [Numeric] The line of the method call.
|
12
|
+
#
|
13
|
+
# @!attribute [r] column
|
14
|
+
# @return [Numeric] The column of the method call.
|
15
|
+
#
|
16
|
+
# @!attribute [r] file
|
17
|
+
# @return [String] The file of the method call.
|
18
|
+
#
|
19
|
+
class MethodCallInfo
|
20
|
+
attr_reader :definition, :line, :column, :file
|
21
|
+
|
22
|
+
##
|
23
|
+
# @param [Hash] options
|
24
|
+
#
|
25
|
+
def initialize(options = {})
|
26
|
+
options.each do |key, value|
|
27
|
+
instance_variable_set("@#{key}", value) if respond_to?(key)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end # MethodCallInfo
|
31
|
+
end # RubyLint
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module RubyLint
|
2
|
+
##
|
3
|
+
# The NodeHash class is used to store information about {RubyLint::AST::Node}
|
4
|
+
# instances based on their SHA1 hashes. It's primarily used by
|
5
|
+
# {RubyLint::Runner} to store nodes and their associated comments.
|
6
|
+
#
|
7
|
+
# @!attribute [r] hash
|
8
|
+
# @return [Hash]
|
9
|
+
#
|
10
|
+
class NodeHash
|
11
|
+
attr_reader :hash
|
12
|
+
|
13
|
+
##
|
14
|
+
# Creates a new instance from a regular Hash.
|
15
|
+
#
|
16
|
+
# @param [Hash] hash
|
17
|
+
# @return [RubyLint::NodeHash]
|
18
|
+
#
|
19
|
+
def self.from_hash(hash)
|
20
|
+
converted = {}
|
21
|
+
|
22
|
+
hash.each do |key, value|
|
23
|
+
converted[key.sha1] = value
|
24
|
+
end
|
25
|
+
|
26
|
+
return new(converted)
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# @param [Hash] hash
|
31
|
+
#
|
32
|
+
def initialize(hash = {})
|
33
|
+
@hash = hash
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Returns the value associated with the given node.
|
38
|
+
#
|
39
|
+
# @param [RubyLint::AST::Node] node
|
40
|
+
# @return [Mixed]
|
41
|
+
#
|
42
|
+
def [](node)
|
43
|
+
return @hash[node.sha1]
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Checks if there's a value stored for the node.
|
48
|
+
#
|
49
|
+
# @param [RubyLint::AST::Node] node
|
50
|
+
# @return [TrueClass|FalseClass]
|
51
|
+
#
|
52
|
+
def key?(node)
|
53
|
+
return @hash.key?(node.sha1)
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Sets a value for the given node.
|
58
|
+
#
|
59
|
+
# @param [RubyLint::AST::Node] node
|
60
|
+
# @param [Mixed] value
|
61
|
+
#
|
62
|
+
def []=(node, value)
|
63
|
+
return @hash[node.sha1] = value
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# @return [Array]
|
68
|
+
#
|
69
|
+
def keys
|
70
|
+
return @hash.keys
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# @return [Array]
|
75
|
+
#
|
76
|
+
def values
|
77
|
+
return @hash.values
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# @return [Array]
|
82
|
+
#
|
83
|
+
def to_a
|
84
|
+
return @hash.to_a
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Merges the values of another NodeHash into the current one.
|
89
|
+
#
|
90
|
+
# @param [RubyLint::NodeHash] other
|
91
|
+
#
|
92
|
+
def merge!(other)
|
93
|
+
@hash.merge!(other.hash)
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Merges a regular Hash into the current NodeHash.
|
98
|
+
#
|
99
|
+
# @param [Hash] hash
|
100
|
+
#
|
101
|
+
def merge_hash!(hash)
|
102
|
+
merge!(self.class.from_hash(hash))
|
103
|
+
end
|
104
|
+
end # NodeHash
|
105
|
+
end # RubyLint
|
data/lib/ruby-lint/parser.rb
CHANGED
@@ -39,11 +39,13 @@ module RubyLint
|
|
39
39
|
buffer = ::Parser::Source::Buffer.new(file, line)
|
40
40
|
buffer.source = code
|
41
41
|
ast, comments = internal_parser.parse_with_comments(buffer)
|
42
|
-
associator = ::Parser::Source::Comment::Associator.new(
|
42
|
+
associator = ::Parser::Source::Comment::Associator.new(ast, comments)
|
43
43
|
|
44
44
|
internal_parser.reset
|
45
45
|
|
46
|
-
|
46
|
+
root = AST::Node.new(:root, [ast], :location => ast.location)
|
47
|
+
|
48
|
+
return root, associator.associate
|
47
49
|
end
|
48
50
|
end # Parser
|
49
51
|
end # RubyLint
|
data/lib/ruby-lint/runner.rb
CHANGED
@@ -7,14 +7,20 @@ module RubyLint
|
|
7
7
|
# @!attribute [r] configuration
|
8
8
|
# @return [RubyLint::Configuration]
|
9
9
|
#
|
10
|
+
# @!attribute [r] cache
|
11
|
+
# @return [RubyLint::Cache]
|
12
|
+
#
|
10
13
|
class Runner
|
11
|
-
attr_reader :configuration
|
14
|
+
attr_reader :configuration, :cache
|
12
15
|
|
13
16
|
##
|
14
17
|
# @param [RubyLint::Configuration] configuration
|
15
18
|
#
|
16
19
|
def initialize(configuration)
|
17
|
-
@configuration
|
20
|
+
@configuration = configuration
|
21
|
+
@cache = Cache.new(configuration.cache_directory)
|
22
|
+
|
23
|
+
@cache.create_directory! if configuration.enable_cache
|
18
24
|
end
|
19
25
|
|
20
26
|
##
|
@@ -77,7 +83,9 @@ module RubyLint
|
|
77
83
|
# @return [Array]
|
78
84
|
#
|
79
85
|
def parse_file(parser, file)
|
80
|
-
|
86
|
+
ast, comments = parser.parse(File.read(file), file)
|
87
|
+
|
88
|
+
return ast, NodeHash.from_hash(comments)
|
81
89
|
end
|
82
90
|
|
83
91
|
##
|
@@ -98,6 +106,10 @@ module RubyLint
|
|
98
106
|
# @return [Array]
|
99
107
|
#
|
100
108
|
def process_external_files(root_ast)
|
109
|
+
if cached_values = get_cache(root_ast)
|
110
|
+
return cached_values
|
111
|
+
end
|
112
|
+
|
101
113
|
loader = FileLoader.new(
|
102
114
|
:directories => configuration.directories,
|
103
115
|
:ignore_paths => configuration.ignore_paths,
|
@@ -105,16 +117,21 @@ module RubyLint
|
|
105
117
|
)
|
106
118
|
|
107
119
|
nodes = []
|
108
|
-
|
120
|
+
mtimes = {}
|
121
|
+
comments = NodeHash.new
|
109
122
|
|
110
123
|
loader.iterate(root_ast)
|
111
124
|
|
112
|
-
loader.nodes.each do |(ast,
|
125
|
+
loader.nodes.each do |(ast, comment_associations)|
|
113
126
|
nodes << ast
|
114
127
|
|
115
|
-
|
128
|
+
mtimes[ast.file] = File.mtime(ast.file) if configuration.enable_cache
|
129
|
+
|
130
|
+
comments.merge_hash!(comment_associations)
|
116
131
|
end
|
117
132
|
|
133
|
+
set_cache(root_ast, nodes, comments, mtimes)
|
134
|
+
|
118
135
|
return nodes, comments
|
119
136
|
end
|
120
137
|
|
@@ -158,5 +175,44 @@ module RubyLint
|
|
158
175
|
instance.iterate(ast)
|
159
176
|
end
|
160
177
|
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# Checks if the AST node has a cache file and if so returns the nodes and
|
181
|
+
# comments that are cached.
|
182
|
+
#
|
183
|
+
# @param [RubyLint::AST::Node] node
|
184
|
+
# @return [Array]
|
185
|
+
#
|
186
|
+
def get_cache(node)
|
187
|
+
return unless configuration.enable_cache
|
188
|
+
|
189
|
+
cache_name = node.sha1
|
190
|
+
|
191
|
+
if cache.exists?(cache_name)
|
192
|
+
entry = cache.get(cache_name)
|
193
|
+
|
194
|
+
if entry.valid?
|
195
|
+
return entry.nodes, entry.comments
|
196
|
+
else
|
197
|
+
cache.delete(cache_name)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
return
|
202
|
+
end
|
203
|
+
|
204
|
+
##
|
205
|
+
# Caches the values for the given node.
|
206
|
+
#
|
207
|
+
# @param [RubyLint::AST::Node] node
|
208
|
+
# @param [Array] nodes
|
209
|
+
# @param [RubyLint::NodeHash] comments
|
210
|
+
# @param [Hash] mtimes
|
211
|
+
#
|
212
|
+
def set_cache(node, nodes, comments, mtimes)
|
213
|
+
return unless configuration.enable_cache
|
214
|
+
|
215
|
+
cache.set(node.sha1, CacheEntry.new(nodes, comments, mtimes))
|
216
|
+
end
|
161
217
|
end # Runner
|
162
218
|
end # RubyLint
|
data/lib/ruby-lint/version.rb
CHANGED
@@ -195,7 +195,7 @@ module RubyLint
|
|
195
195
|
#
|
196
196
|
# @param [RubyLint::AST::Node] node
|
197
197
|
#
|
198
|
-
def on_assign
|
198
|
+
def on_assign
|
199
199
|
reset_assignment_value
|
200
200
|
value_stack.add_stack
|
201
201
|
end
|
@@ -212,10 +212,10 @@ module RubyLint
|
|
212
212
|
value = assignment_value
|
213
213
|
end
|
214
214
|
|
215
|
-
assign_variable(type, name, value)
|
215
|
+
assign_variable(type, name, value, node)
|
216
216
|
end
|
217
217
|
|
218
|
-
ASSIGNMENT_TYPES.each do |callback,
|
218
|
+
ASSIGNMENT_TYPES.each do |callback, _|
|
219
219
|
alias_method :"on_#{callback}", :on_assign
|
220
220
|
alias_method :"after_#{callback}", :after_assign
|
221
221
|
end
|
@@ -259,7 +259,7 @@ module RubyLint
|
|
259
259
|
##
|
260
260
|
# @param [RubyLint::AST::Node] node
|
261
261
|
#
|
262
|
-
def on_masgn
|
262
|
+
def on_masgn
|
263
263
|
add_stacks
|
264
264
|
end
|
265
265
|
|
@@ -267,9 +267,7 @@ module RubyLint
|
|
267
267
|
# Processes a mass variable assignment using the stacks created by
|
268
268
|
# {#on_masgn}.
|
269
269
|
#
|
270
|
-
|
271
|
-
#
|
272
|
-
def after_masgn(node)
|
270
|
+
def after_masgn
|
273
271
|
variables = variable_stack.pop
|
274
272
|
values = value_stack.pop.first
|
275
273
|
values = values && values.value ? values.value : []
|
@@ -284,16 +282,14 @@ module RubyLint
|
|
284
282
|
##
|
285
283
|
# @param [RubyLint::AST::Node] node
|
286
284
|
#
|
287
|
-
def on_or_asgn
|
285
|
+
def on_or_asgn
|
288
286
|
add_stacks
|
289
287
|
end
|
290
288
|
|
291
289
|
##
|
292
290
|
# Processes an `or` assignment in the form of `variable ||= value`.
|
293
291
|
#
|
294
|
-
|
295
|
-
#
|
296
|
-
def after_or_asgn(node)
|
292
|
+
def after_or_asgn
|
297
293
|
variable = variable_stack.pop.first
|
298
294
|
value = value_stack.pop.first
|
299
295
|
|
@@ -305,7 +301,7 @@ module RubyLint
|
|
305
301
|
##
|
306
302
|
# @param [RubyLint::AST::Node] node
|
307
303
|
#
|
308
|
-
def on_and_asgn
|
304
|
+
def on_and_asgn
|
309
305
|
add_stacks
|
310
306
|
end
|
311
307
|
|
@@ -314,7 +310,7 @@ module RubyLint
|
|
314
310
|
#
|
315
311
|
# @param [RubyLint::AST::Node] node
|
316
312
|
#
|
317
|
-
def after_and_asgn
|
313
|
+
def after_and_asgn
|
318
314
|
variable = variable_stack.pop.first
|
319
315
|
value = value_stack.pop.first
|
320
316
|
|
@@ -330,7 +326,7 @@ module RubyLint
|
|
330
326
|
|
331
327
|
# Creates the callback methods for various variable types such as local
|
332
328
|
# variables.
|
333
|
-
ASSIGNMENT_TYPES.each do |
|
329
|
+
ASSIGNMENT_TYPES.each do |_, type|
|
334
330
|
define_method("on_#{type}") do |node|
|
335
331
|
increment_reference_amount(node)
|
336
332
|
push_variable_value(node)
|
@@ -361,9 +357,9 @@ module RubyLint
|
|
361
357
|
end
|
362
358
|
|
363
359
|
##
|
364
|
-
#
|
360
|
+
# Adds a new stack for Array values.
|
365
361
|
#
|
366
|
-
def on_array
|
362
|
+
def on_array
|
367
363
|
value_stack.add_stack
|
368
364
|
end
|
369
365
|
|
@@ -383,9 +379,9 @@ module RubyLint
|
|
383
379
|
end
|
384
380
|
|
385
381
|
##
|
386
|
-
#
|
382
|
+
# Adds a new stack for Hash values.
|
387
383
|
#
|
388
|
-
def on_hash
|
384
|
+
def on_hash
|
389
385
|
value_stack.add_stack
|
390
386
|
end
|
391
387
|
|
@@ -405,18 +401,16 @@ module RubyLint
|
|
405
401
|
end
|
406
402
|
|
407
403
|
##
|
408
|
-
#
|
404
|
+
# Adds a new value stack for key/value pairs.
|
409
405
|
#
|
410
|
-
def on_pair
|
406
|
+
def on_pair
|
411
407
|
value_stack.add_stack
|
412
408
|
end
|
413
409
|
|
414
410
|
##
|
415
|
-
#
|
416
|
-
#
|
417
|
-
# @param [RubyLint::AST::Node] node
|
411
|
+
# @see #on_pair
|
418
412
|
#
|
419
|
-
def after_pair
|
413
|
+
def after_pair
|
420
414
|
key, value = value_stack.pop
|
421
415
|
|
422
416
|
return unless key
|
@@ -431,9 +425,9 @@ module RubyLint
|
|
431
425
|
end
|
432
426
|
|
433
427
|
##
|
434
|
-
#
|
428
|
+
# Pushes the value of `self` onto the current stack.
|
435
429
|
#
|
436
|
-
def on_self
|
430
|
+
def on_self
|
437
431
|
push_value(current_scope.lookup(:keyword, 'self'))
|
438
432
|
end
|
439
433
|
|
@@ -447,9 +441,9 @@ module RubyLint
|
|
447
441
|
end
|
448
442
|
|
449
443
|
##
|
450
|
-
#
|
444
|
+
# Pops the scope created by the module.
|
451
445
|
#
|
452
|
-
def after_module
|
446
|
+
def after_module
|
453
447
|
pop_scope
|
454
448
|
end
|
455
449
|
|
@@ -474,9 +468,9 @@ module RubyLint
|
|
474
468
|
end
|
475
469
|
|
476
470
|
##
|
477
|
-
#
|
471
|
+
# Pops the scope created by the class.
|
478
472
|
#
|
479
|
-
def after_class
|
473
|
+
def after_class
|
480
474
|
pop_scope
|
481
475
|
end
|
482
476
|
|
@@ -495,9 +489,9 @@ module RubyLint
|
|
495
489
|
end
|
496
490
|
|
497
491
|
##
|
498
|
-
#
|
492
|
+
# Pops the scope created by the block.
|
499
493
|
#
|
500
|
-
def after_block
|
494
|
+
def after_block
|
501
495
|
pop_scope
|
502
496
|
end
|
503
497
|
|
@@ -521,9 +515,10 @@ module RubyLint
|
|
521
515
|
end
|
522
516
|
|
523
517
|
##
|
524
|
-
#
|
518
|
+
# Pops the scope created by the `sclass` block and resets the method
|
519
|
+
# definition/send type.
|
525
520
|
#
|
526
|
-
def after_sclass
|
521
|
+
def after_sclass
|
527
522
|
reset_method_type
|
528
523
|
pop_scope
|
529
524
|
end
|
@@ -569,9 +564,7 @@ module RubyLint
|
|
569
564
|
##
|
570
565
|
# Exports various variables to the outer scope of the method definition.
|
571
566
|
#
|
572
|
-
|
573
|
-
#
|
574
|
-
def after_def(node)
|
567
|
+
def after_def
|
575
568
|
previous = pop_scope
|
576
569
|
current = current_scope
|
577
570
|
|
@@ -584,7 +577,7 @@ module RubyLint
|
|
584
577
|
|
585
578
|
# Creates callbacks for various argument types such as :arg and :optarg.
|
586
579
|
ARGUMENT_TYPES.each do |type|
|
587
|
-
define_method("on_#{type}") do
|
580
|
+
define_method("on_#{type}") do
|
588
581
|
value_stack.add_stack
|
589
582
|
end
|
590
583
|
|
@@ -686,21 +679,24 @@ Received: #{arguments.length}
|
|
686
679
|
retval = context.call_method(name)
|
687
680
|
|
688
681
|
retval ? push_value(retval) : push_unknown_value
|
682
|
+
|
683
|
+
# Track the method call
|
684
|
+
track_method_call(context, name, node)
|
689
685
|
else
|
690
686
|
push_unknown_value
|
691
687
|
end
|
692
688
|
end
|
693
689
|
|
694
690
|
VISIBILITIES.each do |vis|
|
695
|
-
define_method("on_send_#{vis}") do
|
691
|
+
define_method("on_send_#{vis}") do
|
696
692
|
@visibility = vis
|
697
693
|
end
|
698
694
|
end
|
699
695
|
|
700
696
|
##
|
701
|
-
#
|
697
|
+
# Adds a new value stack for the values of an alias.
|
702
698
|
#
|
703
|
-
def on_alias
|
699
|
+
def on_alias
|
704
700
|
value_stack.add_stack
|
705
701
|
end
|
706
702
|
|
@@ -867,8 +863,9 @@ Received: #{arguments.length}
|
|
867
863
|
# @param [Symbol] type The type of variable.
|
868
864
|
# @param [String] name The name of the variable
|
869
865
|
# @param [RubyLint::Definition::RubyObject] value
|
866
|
+
# @param [RubyLint::AST::Node] node
|
870
867
|
#
|
871
|
-
def assign_variable(type, name, value)
|
868
|
+
def assign_variable(type, name, value, node)
|
872
869
|
existing = current_scope.lookup(type, name)
|
873
870
|
ref_amount = existing ? existing.reference_amount + 1 : 0
|
874
871
|
variable = Definition::RubyObject.new(
|
@@ -876,7 +873,10 @@ Received: #{arguments.length}
|
|
876
873
|
:name => name,
|
877
874
|
:value => value,
|
878
875
|
:instance_type => :instance,
|
879
|
-
:reference_amount => ref_amount
|
876
|
+
:reference_amount => ref_amount,
|
877
|
+
:line => node.line,
|
878
|
+
:column => node.column,
|
879
|
+
:file => node.file
|
880
880
|
)
|
881
881
|
|
882
882
|
buffer_assignment_value(variable.value)
|
@@ -1117,5 +1117,37 @@ Received: #{arguments.length}
|
|
1117
1117
|
# first one but there should be a nicer way to do this.
|
1118
1118
|
definition.returns(definitions[0]) if definitions[0]
|
1119
1119
|
end
|
1120
|
+
|
1121
|
+
##
|
1122
|
+
# Tracks a method call.
|
1123
|
+
#
|
1124
|
+
# @param [RubyLint::Definition::RubyMethod] definition
|
1125
|
+
# @param [String] name
|
1126
|
+
# @param [RubyLint::AST::Node] node
|
1127
|
+
#
|
1128
|
+
def track_method_call(definition, name, node)
|
1129
|
+
method = definition.lookup(definition.method_call_type, name)
|
1130
|
+
current = current_scope
|
1131
|
+
location = {
|
1132
|
+
:line => node.line,
|
1133
|
+
:column => node.column,
|
1134
|
+
:file => node.file
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
# Add the call to the current scope if we're dealing with a writable
|
1138
|
+
# method definition.
|
1139
|
+
if current.respond_to?(:calls) and !current.frozen?
|
1140
|
+
current.calls.push(
|
1141
|
+
MethodCallInfo.new(location.merge(:definition => method))
|
1142
|
+
)
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
# Add the caller to the called method, this allows for inverse lookups.
|
1146
|
+
unless method.frozen?
|
1147
|
+
method.callers.push(
|
1148
|
+
MethodCallInfo.new(location.merge(:definition => definition))
|
1149
|
+
)
|
1150
|
+
end
|
1151
|
+
end
|
1120
1152
|
end # VirtualMachine
|
1121
1153
|
end # RubyLint
|