leftovers 0.2.2 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|