leftovers 0.2.2 → 0.4.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +41 -0
- data/README.md +35 -49
- data/docs/Configuration.md +627 -0
- data/exe/leftovers +2 -2
- data/leftovers.gemspec +13 -7
- data/lib/config/attr_encrypted.yml +3 -4
- data/lib/config/audited.yml +9 -4
- data/lib/config/datagrid.yml +1 -1
- data/lib/config/flipper.yml +1 -3
- data/lib/config/graphql.yml +15 -13
- data/lib/config/okcomputer.yml +1 -3
- data/lib/config/parser.yml +89 -91
- data/lib/config/rails.yml +160 -97
- data/lib/config/redcarpet.yml +35 -38
- data/lib/config/rollbar.yml +1 -3
- data/lib/config/rspec.yml +18 -10
- data/lib/config/ruby.yml +42 -49
- data/lib/config/selenium-webdriver.yml +19 -0
- data/lib/config/sidekiq.yml +9 -0
- data/lib/config/will_paginate.yml +12 -14
- data/lib/leftovers.rb +61 -43
- data/lib/leftovers/ast.rb +8 -0
- data/lib/leftovers/ast/builder.rb +6 -3
- data/lib/leftovers/ast/node.rb +66 -107
- data/lib/leftovers/backports.rb +24 -40
- data/lib/leftovers/cli.rb +17 -14
- data/lib/leftovers/collector.rb +7 -11
- data/lib/leftovers/config.rb +38 -13
- data/lib/leftovers/config_validator.rb +60 -0
- data/lib/leftovers/config_validator/error_processor.rb +196 -0
- data/lib/leftovers/config_validator/schema_hash.rb +496 -0
- data/lib/leftovers/definition.rb +16 -41
- data/lib/leftovers/definition_node.rb +36 -0
- data/lib/leftovers/definition_set.rb +17 -24
- data/lib/leftovers/dynamic_processors.rb +11 -0
- data/lib/leftovers/dynamic_processors/call.rb +25 -0
- data/lib/leftovers/dynamic_processors/call_definition.rb +31 -0
- data/lib/leftovers/dynamic_processors/definition.rb +26 -0
- data/lib/leftovers/dynamic_processors/each.rb +19 -0
- data/lib/leftovers/dynamic_processors/null.rb +9 -0
- data/lib/leftovers/erb.rb +2 -2
- data/lib/leftovers/file.rb +3 -5
- data/lib/leftovers/file_collector.rb +82 -62
- data/lib/leftovers/file_list.rb +9 -15
- data/lib/leftovers/haml.rb +9 -12
- data/lib/leftovers/matcher_builders.rb +24 -0
- data/lib/leftovers/matcher_builders/and.rb +19 -0
- data/lib/leftovers/matcher_builders/and_not.rb +14 -0
- data/lib/leftovers/matcher_builders/argument_node_value.rb +21 -0
- data/lib/leftovers/matcher_builders/name.rb +29 -0
- data/lib/leftovers/matcher_builders/node.rb +40 -0
- data/lib/leftovers/matcher_builders/node_has_argument.rb +71 -0
- data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +22 -0
- data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +24 -0
- data/lib/leftovers/matcher_builders/node_name.rb +15 -0
- data/lib/leftovers/matcher_builders/node_pair_name.rb +18 -0
- data/lib/leftovers/matcher_builders/node_pair_value.rb +16 -0
- data/lib/leftovers/matcher_builders/node_path.rb +14 -0
- data/lib/leftovers/matcher_builders/node_type.rb +28 -0
- data/lib/leftovers/matcher_builders/or.rb +73 -0
- data/lib/leftovers/matcher_builders/path.rb +15 -0
- data/lib/leftovers/matcher_builders/string.rb +11 -0
- data/lib/leftovers/matcher_builders/string_pattern.rb +19 -0
- data/lib/leftovers/matcher_builders/unless.rb +13 -0
- data/lib/leftovers/matchers.rb +26 -0
- data/lib/leftovers/matchers/all.rb +25 -0
- data/lib/leftovers/matchers/and.rb +24 -0
- data/lib/leftovers/matchers/any.rb +27 -0
- data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +28 -0
- data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +25 -0
- data/lib/leftovers/matchers/node_has_positional_argument.rb +23 -0
- data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +25 -0
- data/lib/leftovers/matchers/node_name.rb +23 -0
- data/lib/leftovers/matchers/node_pair_value.rb +23 -0
- data/lib/leftovers/matchers/node_path.rb +23 -0
- data/lib/leftovers/matchers/node_scalar_value.rb +25 -0
- data/lib/leftovers/matchers/node_type.rb +23 -0
- data/lib/leftovers/matchers/not.rb +23 -0
- data/lib/leftovers/matchers/or.rb +26 -0
- data/lib/leftovers/merged_config.rb +24 -14
- data/lib/leftovers/parser.rb +2 -5
- data/lib/leftovers/processor_builders.rb +22 -0
- data/lib/leftovers/processor_builders/action.rb +63 -0
- data/lib/leftovers/processor_builders/add_prefix.rb +20 -0
- data/lib/leftovers/processor_builders/add_suffix.rb +20 -0
- data/lib/leftovers/processor_builders/argument.rb +25 -0
- data/lib/leftovers/processor_builders/dynamic.rb +27 -0
- data/lib/leftovers/processor_builders/each.rb +36 -0
- data/lib/leftovers/processor_builders/each_action.rb +51 -0
- data/lib/leftovers/processor_builders/each_dynamic.rb +54 -0
- data/lib/leftovers/processor_builders/each_for_definition_set.rb +36 -0
- data/lib/leftovers/processor_builders/itself.rb +13 -0
- data/lib/leftovers/processor_builders/keyword.rb +24 -0
- data/lib/leftovers/processor_builders/keyword_argument.rb +14 -0
- data/lib/leftovers/processor_builders/transform.rb +55 -0
- data/lib/leftovers/processor_builders/transform_chain.rb +24 -0
- data/lib/leftovers/processor_builders/transform_set.rb +47 -0
- data/lib/leftovers/processor_builders/value.rb +13 -0
- data/lib/leftovers/rake_task.rb +4 -4
- data/lib/leftovers/reporter.rb +1 -1
- data/lib/leftovers/value_processors.rb +40 -0
- data/lib/leftovers/value_processors/add_dynamic_prefix.rb +31 -0
- data/lib/leftovers/value_processors/add_dynamic_suffix.rb +31 -0
- data/lib/leftovers/value_processors/add_prefix.rb +20 -0
- data/lib/leftovers/value_processors/add_suffix.rb +20 -0
- data/lib/leftovers/value_processors/camelize.rb +24 -0
- data/lib/leftovers/value_processors/capitalize.rb +19 -0
- data/lib/leftovers/value_processors/deconstantize.rb +24 -0
- data/lib/leftovers/value_processors/delete_after.rb +22 -0
- data/lib/leftovers/value_processors/delete_before.rb +22 -0
- data/lib/leftovers/value_processors/delete_prefix.rb +26 -0
- data/lib/leftovers/value_processors/delete_suffix.rb +26 -0
- data/lib/leftovers/value_processors/demodulize.rb +24 -0
- data/lib/leftovers/value_processors/downcase.rb +19 -0
- data/lib/leftovers/value_processors/each.rb +21 -0
- data/lib/leftovers/value_processors/each_for_definition_set.rb +29 -0
- data/lib/leftovers/value_processors/each_keyword.rb +27 -0
- data/lib/leftovers/value_processors/each_keyword_argument.rb +27 -0
- data/lib/leftovers/value_processors/each_positional_argument.rb +24 -0
- data/lib/leftovers/value_processors/itself.rb +17 -0
- data/lib/leftovers/value_processors/keyword.rb +36 -0
- data/lib/leftovers/value_processors/keyword_argument.rb +36 -0
- data/lib/leftovers/value_processors/parameterize.rb +24 -0
- data/lib/leftovers/value_processors/placeholder.rb +18 -0
- data/lib/leftovers/value_processors/pluralize.rb +24 -0
- data/lib/leftovers/value_processors/positional_argument.rb +26 -0
- data/lib/leftovers/value_processors/replace_value.rb +18 -0
- data/lib/leftovers/value_processors/return_definition.rb +26 -0
- data/lib/leftovers/value_processors/return_string.rb +14 -0
- data/lib/leftovers/value_processors/singularize.rb +24 -0
- data/lib/leftovers/value_processors/split.rb +22 -0
- data/lib/leftovers/value_processors/swapcase.rb +19 -0
- data/lib/leftovers/value_processors/titleize.rb +24 -0
- data/lib/leftovers/value_processors/underscore.rb +24 -0
- data/lib/leftovers/value_processors/upcase.rb +19 -0
- data/lib/leftovers/version.rb +1 -1
- metadata +190 -28
- data/lib/config/selenium.yml +0 -21
- data/lib/leftovers/argument_rule.rb +0 -219
- data/lib/leftovers/core_ext.rb +0 -13
- data/lib/leftovers/hash_rule.rb +0 -40
- data/lib/leftovers/name_rule.rb +0 -53
- data/lib/leftovers/rule.rb +0 -74
- data/lib/leftovers/transform_rule.rb +0 -171
- data/lib/leftovers/value_rule.rb +0 -56
data/lib/leftovers/definition.rb
CHANGED
|
@@ -2,57 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
module Leftovers
|
|
4
4
|
class Definition
|
|
5
|
-
attr_reader :name
|
|
5
|
+
attr_reader :name, :test, :location_s
|
|
6
6
|
alias_method :names, :name
|
|
7
|
-
|
|
8
|
-
attr_reader :name_s
|
|
9
|
-
alias_method :to_s, :name_s
|
|
10
|
-
attr_reader :test
|
|
7
|
+
|
|
11
8
|
alias_method :test?, :test
|
|
12
9
|
|
|
13
|
-
def initialize(
|
|
10
|
+
def initialize(
|
|
14
11
|
name,
|
|
15
|
-
method_node: nil,
|
|
16
12
|
location: method_node.loc.expression,
|
|
17
|
-
|
|
18
|
-
test: method_node.test?
|
|
13
|
+
test: method_node.test_line?
|
|
19
14
|
)
|
|
20
15
|
@name = name
|
|
21
|
-
@
|
|
22
|
-
|
|
23
|
-
@
|
|
24
|
-
@
|
|
16
|
+
@path = location.source_buffer.name.to_s
|
|
17
|
+
@location_source_line = location.source_line.to_s
|
|
18
|
+
@location_column_range_begin = location.column_range.begin.to_i
|
|
19
|
+
@location_column_range_end = location.column_range.end.to_i
|
|
20
|
+
@location_source = location.source.to_s
|
|
21
|
+
@location_s = location.to_s
|
|
25
22
|
@test = test
|
|
26
23
|
|
|
27
24
|
freeze
|
|
28
25
|
end
|
|
29
26
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
(line <=> other.line).nonzero? ||
|
|
33
|
-
(column <=> other.column)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def path
|
|
37
|
-
@file.relative_path
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def line
|
|
41
|
-
@location.line
|
|
27
|
+
def to_s
|
|
28
|
+
@name.to_s
|
|
42
29
|
end
|
|
43
30
|
|
|
44
|
-
def
|
|
45
|
-
@
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def full_location
|
|
49
|
-
"#{path}:#{@location.line}:#{@location.column}"
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def highlighted_source(highlight = "\e[31m", normal = "\e[0m") # rubocop:disable Metrics/AbcSize
|
|
53
|
-
@location.source_line.to_s[0...(@location.column_range.begin)].lstrip +
|
|
54
|
-
highlight + @location.source.to_s + normal +
|
|
55
|
-
@location.source_line.to_s[(@location.column_range.end)..-1].rstrip
|
|
31
|
+
def highlighted_source(highlight = "\e[31m", normal = "\e[0m")
|
|
32
|
+
@location_source_line[0...@location_column_range_begin].lstrip +
|
|
33
|
+
highlight + @location_source + normal +
|
|
34
|
+
@location_source_line[@location_column_range_end..-1].rstrip
|
|
56
35
|
end
|
|
57
36
|
|
|
58
37
|
def in_collection?
|
|
@@ -62,9 +41,5 @@ module Leftovers
|
|
|
62
41
|
def in_test_collection?
|
|
63
42
|
Leftovers.collector.test_calls.include?(@name)
|
|
64
43
|
end
|
|
65
|
-
|
|
66
|
-
def skipped?
|
|
67
|
-
Leftovers.config.skip_rules.any? { |r| r.match?(@name, @name_s, path) }
|
|
68
|
-
end
|
|
69
44
|
end
|
|
70
45
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
# To give to matchers before creating a Definition
|
|
4
|
+
|
|
5
|
+
module Leftovers
|
|
6
|
+
class DefinitionNode
|
|
7
|
+
attr_reader :path, :name
|
|
8
|
+
|
|
9
|
+
def initialize(name, path)
|
|
10
|
+
@name = name
|
|
11
|
+
@path = path
|
|
12
|
+
|
|
13
|
+
freeze
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# these are the methods checked by things in lib/leftovers/matchers
|
|
17
|
+
def kwargs
|
|
18
|
+
nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def positional_arguments
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# these two i'm not sure are possible with the current config flags
|
|
26
|
+
# :nocov:
|
|
27
|
+
def scalar?
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def type
|
|
32
|
+
:leftovers_definition
|
|
33
|
+
end
|
|
34
|
+
# :nocov:
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'definition'
|
|
4
3
|
module Leftovers
|
|
5
|
-
class DefinitionSet
|
|
6
|
-
|
|
7
|
-
names,
|
|
8
|
-
method_node: nil,
|
|
9
|
-
location: method_node.loc.expression,
|
|
10
|
-
file: method_node.file,
|
|
11
|
-
test: method_node.test?
|
|
12
|
-
)
|
|
13
|
-
@definitions = names.map do |name|
|
|
14
|
-
Leftovers::Definition.new(name, test: test, location: location, file: file)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
@test = test
|
|
18
|
-
@location = location
|
|
19
|
-
@file = file
|
|
4
|
+
class DefinitionSet
|
|
5
|
+
attr_reader :definitions
|
|
20
6
|
|
|
21
|
-
|
|
22
|
-
|
|
7
|
+
def initialize(definitions)
|
|
8
|
+
@definitions = definitions
|
|
23
9
|
|
|
24
|
-
|
|
25
|
-
names.join(', ')
|
|
10
|
+
freeze
|
|
26
11
|
end
|
|
27
12
|
|
|
28
13
|
def names
|
|
@@ -33,16 +18,24 @@ module Leftovers
|
|
|
33
18
|
@definitions.map(&:to_s).join(', ')
|
|
34
19
|
end
|
|
35
20
|
|
|
21
|
+
def location_s
|
|
22
|
+
@definitions.first.location_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def highlighted_source(*args)
|
|
26
|
+
@definitions.first.highlighted_source(*args)
|
|
27
|
+
end
|
|
28
|
+
|
|
36
29
|
def in_collection?
|
|
37
30
|
@definitions.any?(&:in_collection?)
|
|
38
31
|
end
|
|
39
32
|
|
|
40
|
-
def
|
|
41
|
-
@definitions.any?(&:
|
|
33
|
+
def test?
|
|
34
|
+
@definitions.any?(&:test?)
|
|
42
35
|
end
|
|
43
36
|
|
|
44
|
-
def
|
|
45
|
-
@definitions.any?(&:
|
|
37
|
+
def in_test_collection?
|
|
38
|
+
@definitions.any?(&:in_test_collection?)
|
|
46
39
|
end
|
|
47
40
|
end
|
|
48
41
|
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Leftovers
|
|
4
|
+
module DynamicProcessors
|
|
5
|
+
autoload(:CallDefinition, "#{__dir__}/dynamic_processors/call_definition")
|
|
6
|
+
autoload(:Call, "#{__dir__}/dynamic_processors/call")
|
|
7
|
+
autoload(:Definition, "#{__dir__}/dynamic_processors/definition")
|
|
8
|
+
autoload(:Each, "#{__dir__}/dynamic_processors/each")
|
|
9
|
+
autoload(:Null, "#{__dir__}/dynamic_processors/null")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Leftovers
|
|
4
|
+
module DynamicProcessors
|
|
5
|
+
class Call
|
|
6
|
+
# :nocov:
|
|
7
|
+
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
|
8
|
+
# :nocov:
|
|
9
|
+
|
|
10
|
+
def initialize(matcher, processor)
|
|
11
|
+
@matcher = matcher
|
|
12
|
+
@processor = processor
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def process(node, file)
|
|
16
|
+
return unless @matcher === node
|
|
17
|
+
|
|
18
|
+
call = @processor.process(nil, node, node)
|
|
19
|
+
return unless call
|
|
20
|
+
|
|
21
|
+
file.calls << call
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Leftovers
|
|
4
|
+
module DynamicProcessors
|
|
5
|
+
class CallDefinition
|
|
6
|
+
# :nocov:
|
|
7
|
+
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
|
8
|
+
# :nocov:
|
|
9
|
+
|
|
10
|
+
def initialize(matcher, call_processor, definition_processor)
|
|
11
|
+
@matcher = matcher
|
|
12
|
+
@call_processor = call_processor
|
|
13
|
+
@definition_processor = definition_processor
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def process(node, file)
|
|
17
|
+
return unless @matcher === node
|
|
18
|
+
|
|
19
|
+
call = @call_processor.process(nil, node, node)
|
|
20
|
+
(file.calls << call) if call
|
|
21
|
+
|
|
22
|
+
return if node.keep_line?
|
|
23
|
+
|
|
24
|
+
definition = @definition_processor.process(nil, node, node)
|
|
25
|
+
return unless definition
|
|
26
|
+
|
|
27
|
+
file.definitions << definition
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Leftovers
|
|
4
|
+
module DynamicProcessors
|
|
5
|
+
class Definition
|
|
6
|
+
# :nocov:
|
|
7
|
+
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
|
8
|
+
# :nocov:
|
|
9
|
+
|
|
10
|
+
def initialize(matcher, processor)
|
|
11
|
+
@matcher = matcher
|
|
12
|
+
@processor = processor
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def process(node, file)
|
|
16
|
+
return if node.keep_line?
|
|
17
|
+
return unless @matcher === node
|
|
18
|
+
|
|
19
|
+
definition = @processor.process(nil, node, node)
|
|
20
|
+
return unless definition
|
|
21
|
+
|
|
22
|
+
file.definitions << definition
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Leftovers
|
|
4
|
+
module DynamicProcessors
|
|
5
|
+
class Each
|
|
6
|
+
attr_reader :processors
|
|
7
|
+
|
|
8
|
+
def initialize(processors)
|
|
9
|
+
@processors = processors
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process(node, file)
|
|
13
|
+
@processors.each do |processor|
|
|
14
|
+
processor.process(node, file)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/leftovers/erb.rb
CHANGED
|
@@ -9,11 +9,11 @@ module Leftovers
|
|
|
9
9
|
@compiler.compile(erb).first
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def add_insert_cmd(out, content)
|
|
12
|
+
def add_insert_cmd(out, content) # leftovers:keep
|
|
13
13
|
out.push("#{content}\n")
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def add_put_cmd(out, _content)
|
|
16
|
+
def add_put_cmd(out, _content) # leftovers:keep
|
|
17
17
|
out
|
|
18
18
|
end
|
|
19
19
|
end
|
data/lib/leftovers/file.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'erb'
|
|
4
|
-
require_relative 'haml'
|
|
5
3
|
require 'pathname'
|
|
6
4
|
|
|
7
5
|
module Leftovers
|
|
@@ -16,12 +14,12 @@ module Leftovers
|
|
|
16
14
|
@test = Leftovers.config.test_paths.allowed?(relative_path)
|
|
17
15
|
end
|
|
18
16
|
|
|
19
|
-
def ruby
|
|
17
|
+
def ruby
|
|
20
18
|
case extname
|
|
21
19
|
when '.haml'
|
|
22
|
-
Leftovers::Haml.precompile(read)
|
|
20
|
+
::Leftovers::Haml.precompile(read, self)
|
|
23
21
|
when '.rhtml', '.rjs', '.erb'
|
|
24
|
-
Leftovers::ERB.precompile(read)
|
|
22
|
+
::Leftovers::ERB.precompile(read)
|
|
25
23
|
else
|
|
26
24
|
read
|
|
27
25
|
end
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'fast_ignore'
|
|
4
3
|
require 'set'
|
|
5
|
-
|
|
6
|
-
require_relative 'definition'
|
|
4
|
+
require 'parser'
|
|
7
5
|
|
|
8
6
|
module Leftovers
|
|
9
7
|
class FileCollector < ::Parser::AST::Processor # rubocop:disable Metrics/ClassLength
|
|
10
|
-
attr_reader :calls
|
|
11
|
-
attr_reader :definitions
|
|
8
|
+
attr_reader :calls, :definitions
|
|
12
9
|
|
|
13
|
-
def initialize(ruby, file) # rubocop:disable
|
|
10
|
+
def initialize(ruby, file) # rubocop:disable Lint/MissingSuper
|
|
14
11
|
@calls = []
|
|
15
12
|
@definitions = []
|
|
16
13
|
@allow_lines = Set.new.compare_by_identity
|
|
@@ -24,6 +21,8 @@ module Leftovers
|
|
|
24
21
|
end
|
|
25
22
|
|
|
26
23
|
def to_h
|
|
24
|
+
squash!
|
|
25
|
+
|
|
27
26
|
{
|
|
28
27
|
test?: @file.test?,
|
|
29
28
|
calls: calls,
|
|
@@ -31,15 +30,25 @@ module Leftovers
|
|
|
31
30
|
}
|
|
32
31
|
end
|
|
33
32
|
|
|
33
|
+
def squash!
|
|
34
|
+
calls.flatten!
|
|
35
|
+
calls.compact!
|
|
36
|
+
calls.uniq!
|
|
37
|
+
definitions.flatten!
|
|
38
|
+
definitions.compact!
|
|
39
|
+
definitions.uniq!
|
|
40
|
+
definitions.reject! { |v| v == :keep }
|
|
41
|
+
end
|
|
42
|
+
|
|
34
43
|
def collect
|
|
35
|
-
ast, comments = Leftovers::Parser.parse_with_comments(@ruby, @file)
|
|
44
|
+
ast, comments = Leftovers::Parser.parse_with_comments(@ruby, @file.relative_path)
|
|
36
45
|
process_comments(comments)
|
|
37
46
|
process(ast)
|
|
38
|
-
rescue Parser::SyntaxError => e
|
|
39
|
-
Leftovers.warn "
|
|
47
|
+
rescue ::Parser::SyntaxError => e
|
|
48
|
+
Leftovers.warn "\e[31m#{filename}:#{e.diagnostic.location.line}:#{e.diagnostic.location.column} SyntaxError: #{e.message}\e[0m" # rubocop:disable Layout/LineLength
|
|
40
49
|
end
|
|
41
50
|
|
|
42
|
-
METHOD_NAME_RE = /[[:alpha:]_][[:alnum:]_]*\b[
|
|
51
|
+
METHOD_NAME_RE = /[[:alpha:]_][[:alnum:]_]*\b[?!=]?/.freeze
|
|
43
52
|
NON_ALNUM_METHOD_NAME_RE = Regexp.union(%w{
|
|
44
53
|
[]= [] ** ~ +@ -@ * / % + - >> << &
|
|
45
54
|
^ | <=> <= >= < > === == != =~ !~ !
|
|
@@ -48,15 +57,13 @@ module Leftovers
|
|
|
48
57
|
NAME_RE = Regexp.union(METHOD_NAME_RE, NON_ALNUM_METHOD_NAME_RE, CONSTANT_NAME_RE)
|
|
49
58
|
LEFTOVERS_CALL_RE = /\bleftovers:call(?:s|ed|er|ers|) (#{NAME_RE}(?:[, :]+#{NAME_RE})*)/.freeze
|
|
50
59
|
LEFTOVERS_ALLOW_RE = /\bleftovers:(?:keeps?|skip(?:s|ped|)|allow(?:s|ed|))\b/.freeze
|
|
51
|
-
LEFTOVERS_TEST_RE = /\bleftovers:(?:for_tests?|tests?|testing)\b/.freeze
|
|
52
|
-
def process_comments(comments) # rubocop:disable Metrics/
|
|
60
|
+
LEFTOVERS_TEST_RE = /\bleftovers:(?:for_tests?|tests?|testing|test_only)\b/.freeze
|
|
61
|
+
def process_comments(comments) # rubocop:disable Metrics/AbcSize
|
|
53
62
|
comments.each do |comment|
|
|
54
63
|
@allow_lines << comment.loc.line if comment.text.match?(LEFTOVERS_ALLOW_RE)
|
|
55
|
-
|
|
56
64
|
@test_lines << comment.loc.line if comment.text.match?(LEFTOVERS_TEST_RE)
|
|
57
65
|
|
|
58
66
|
next unless (match = comment.text.match(LEFTOVERS_CALL_RE))
|
|
59
|
-
next unless match[1]
|
|
60
67
|
|
|
61
68
|
match[1].scan(NAME_RE).each { |s| add_call(s.to_sym) }
|
|
62
69
|
end
|
|
@@ -64,66 +71,75 @@ module Leftovers
|
|
|
64
71
|
|
|
65
72
|
# grab method definitions
|
|
66
73
|
def on_def(node)
|
|
67
|
-
add_definition(node
|
|
68
|
-
|
|
74
|
+
add_definition(node)
|
|
69
75
|
super
|
|
70
76
|
end
|
|
71
77
|
|
|
72
78
|
def on_ivasgn(node)
|
|
73
|
-
|
|
79
|
+
collect_variable_assign(node)
|
|
80
|
+
super
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def on_gvasgn(node)
|
|
84
|
+
collect_variable_assign(node)
|
|
85
|
+
super
|
|
86
|
+
end
|
|
74
87
|
|
|
88
|
+
def on_cvasgn(node)
|
|
89
|
+
collect_variable_assign(node)
|
|
75
90
|
super
|
|
76
91
|
end
|
|
77
|
-
alias_method :on_gvasgn, :on_ivasgn
|
|
78
|
-
alias_method :on_cvasgn, :on_ivasgn
|
|
79
92
|
|
|
80
93
|
def on_ivar(node)
|
|
81
|
-
add_call(node.
|
|
94
|
+
add_call(node.name)
|
|
95
|
+
super
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def on_gvar(node)
|
|
99
|
+
add_call(node.name)
|
|
100
|
+
super
|
|
101
|
+
end
|
|
82
102
|
|
|
103
|
+
def on_cvar(node)
|
|
104
|
+
add_call(node.name)
|
|
83
105
|
super
|
|
84
106
|
end
|
|
85
|
-
alias_method :on_gvar, :on_ivar
|
|
86
|
-
alias_method :on_cvar, :on_ivar
|
|
87
107
|
|
|
88
108
|
def on_op_asgn(node)
|
|
89
109
|
collect_op_asgn(node)
|
|
90
|
-
|
|
91
110
|
super
|
|
92
111
|
end
|
|
93
112
|
|
|
94
113
|
def on_and_asgn(node)
|
|
95
114
|
collect_op_asgn(node)
|
|
96
|
-
|
|
97
115
|
super
|
|
98
116
|
end
|
|
99
117
|
|
|
100
118
|
def on_or_asgn(node)
|
|
101
119
|
collect_op_asgn(node)
|
|
102
|
-
|
|
103
120
|
super
|
|
104
121
|
end
|
|
105
122
|
|
|
106
123
|
# grab method calls
|
|
107
124
|
def on_send(node)
|
|
108
125
|
super
|
|
126
|
+
collect_send(node)
|
|
127
|
+
end
|
|
109
128
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
129
|
+
def on_csend(node)
|
|
130
|
+
super
|
|
131
|
+
collect_send(node)
|
|
113
132
|
end
|
|
114
|
-
alias_method :on_csend, :on_send
|
|
115
133
|
|
|
116
134
|
def on_const(node)
|
|
117
135
|
super
|
|
118
|
-
|
|
119
|
-
add_call(node.children[1])
|
|
136
|
+
add_call(node.name)
|
|
120
137
|
end
|
|
121
138
|
|
|
122
139
|
# grab e.g. :to_s in each(&:to_s)
|
|
123
140
|
def on_block_pass(node)
|
|
124
141
|
super
|
|
125
|
-
|
|
126
|
-
add_call(node.children.first.to_sym) if node.children.first&.string_or_symbol?
|
|
142
|
+
add_call(node.children.first.to_sym) if node.children.first.string_or_symbol?
|
|
127
143
|
end
|
|
128
144
|
|
|
129
145
|
# grab class Constant or module Constant
|
|
@@ -134,84 +150,88 @@ module Leftovers
|
|
|
134
150
|
|
|
135
151
|
node = node.children.first
|
|
136
152
|
|
|
137
|
-
add_definition(node
|
|
153
|
+
add_definition(node)
|
|
138
154
|
end
|
|
139
155
|
alias_method :on_module, :on_class
|
|
140
156
|
|
|
141
157
|
# grab Constant = Class.new or CONSTANT = 'string'.freeze
|
|
142
158
|
def on_casgn(node)
|
|
143
159
|
super
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
collect_rules(node)
|
|
160
|
+
add_definition(node)
|
|
161
|
+
collect_dynamic(node)
|
|
148
162
|
end
|
|
149
163
|
|
|
150
164
|
# grab calls to `alias new_method original_method`
|
|
151
165
|
def on_alias(node)
|
|
152
166
|
super
|
|
153
|
-
|
|
154
167
|
new_method, original_method = node.children
|
|
155
|
-
|
|
156
|
-
add_definition(new_method.children.first, new_method.loc.expression)
|
|
168
|
+
add_definition(new_method, name: new_method.children.first, loc: new_method.loc.expression)
|
|
157
169
|
add_call(original_method.children.first)
|
|
158
170
|
end
|
|
159
171
|
|
|
160
172
|
private
|
|
161
173
|
|
|
162
|
-
def
|
|
163
|
-
@file.test? ||
|
|
174
|
+
def test_line?(loc)
|
|
175
|
+
@file.test? ||
|
|
176
|
+
@test_lines.include?(loc.line)
|
|
164
177
|
end
|
|
165
178
|
|
|
166
|
-
def
|
|
179
|
+
def test_node?(node, loc)
|
|
180
|
+
test_line?(loc) || ::Leftovers.config.test_only === node
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def add_definition(node, name: node.name, loc: node.loc.name)
|
|
167
184
|
return if @allow_lines.include?(loc.line)
|
|
185
|
+
return if Leftovers.config.keep === node
|
|
168
186
|
|
|
169
|
-
definitions << Leftovers::Definition.new(name, location: loc,
|
|
187
|
+
definitions << Leftovers::Definition.new(name, location: loc, test: test_node?(node, loc))
|
|
170
188
|
end
|
|
171
189
|
|
|
172
190
|
def add_call(name)
|
|
173
191
|
calls << name
|
|
174
192
|
end
|
|
175
193
|
|
|
194
|
+
def collect_send(node)
|
|
195
|
+
add_call(node.name)
|
|
196
|
+
collect_dynamic(node)
|
|
197
|
+
end
|
|
198
|
+
|
|
176
199
|
# just collects the call, super will collect the definition
|
|
177
200
|
def collect_var_op_asgn(node)
|
|
178
201
|
name = node.children.first
|
|
179
202
|
|
|
180
|
-
return unless name
|
|
181
|
-
|
|
182
203
|
add_call(name)
|
|
183
204
|
end
|
|
184
205
|
|
|
185
206
|
def collect_send_op_asgn(node)
|
|
186
207
|
name = node.children[1]
|
|
187
208
|
|
|
188
|
-
return unless name
|
|
189
|
-
|
|
190
209
|
add_call(:"#{name}=")
|
|
191
210
|
end
|
|
192
211
|
|
|
212
|
+
def collect_variable_assign(node)
|
|
213
|
+
add_definition(node)
|
|
214
|
+
|
|
215
|
+
collect_dynamic(node)
|
|
216
|
+
end
|
|
217
|
+
|
|
193
218
|
def collect_op_asgn(node)
|
|
194
219
|
node = node.children.first
|
|
220
|
+
# :nocov: # don't need else, it's exhaustive for callers
|
|
195
221
|
case node.type
|
|
222
|
+
# :nocov:
|
|
196
223
|
when :send then collect_send_op_asgn(node)
|
|
197
224
|
when :ivasgn, :gvasgn, :cvasgn then collect_var_op_asgn(node)
|
|
198
225
|
end
|
|
199
226
|
end
|
|
200
227
|
|
|
201
|
-
def
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
next if rule.skip?
|
|
206
|
-
|
|
207
|
-
calls.concat(rule.calls(node))
|
|
228
|
+
def collect_dynamic(node) # rubocop:disable Metrics/AbcSize
|
|
229
|
+
node.keep_line = @allow_lines.include?(node.loc.line)
|
|
230
|
+
node.test_line = test_line?(node.loc) unless node.keep_line?
|
|
208
231
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
node.test = test?(node.loc)
|
|
213
|
-
definitions.concat(rule.definitions(node))
|
|
214
|
-
end
|
|
232
|
+
Leftovers.config.dynamic.process(node, self)
|
|
233
|
+
rescue StandardError => e
|
|
234
|
+
raise ::Leftovers::Error, "#{e.class}: #{e.message}\nwhen processing #{node} at #{filename}:#{node.loc.line}:#{node.loc.column}", e.backtrace # rubocop:disable Layout/LineLength
|
|
215
235
|
end
|
|
216
236
|
end
|
|
217
237
|
end
|