leftovers 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/README.md +28 -45
  4. data/docs/Configuration.md +598 -0
  5. data/exe/leftovers +1 -1
  6. data/leftovers.gemspec +9 -6
  7. data/lib/config/attr_encrypted.yml +3 -4
  8. data/lib/config/audited.yml +9 -4
  9. data/lib/config/datagrid.yml +1 -1
  10. data/lib/config/flipper.yml +1 -3
  11. data/lib/config/graphql.yml +15 -13
  12. data/lib/config/okcomputer.yml +1 -3
  13. data/lib/config/parser.yml +89 -91
  14. data/lib/config/rails.yml +125 -107
  15. data/lib/config/redcarpet.yml +35 -38
  16. data/lib/config/rollbar.yml +1 -3
  17. data/lib/config/rspec.yml +18 -10
  18. data/lib/config/ruby.yml +40 -50
  19. data/lib/config/selenium-webdriver.yml +19 -21
  20. data/lib/config/sidekiq.yml +4 -8
  21. data/lib/config/will_paginate.yml +12 -14
  22. data/lib/leftovers.rb +38 -26
  23. data/lib/leftovers/ast.rb +8 -0
  24. data/lib/leftovers/ast/builder.rb +4 -4
  25. data/lib/leftovers/ast/node.rb +50 -77
  26. data/lib/leftovers/backports.rb +27 -23
  27. data/lib/leftovers/cli.rb +0 -3
  28. data/lib/leftovers/collector.rb +4 -8
  29. data/lib/leftovers/config.rb +19 -25
  30. data/lib/leftovers/config_validator.rb +60 -0
  31. data/lib/leftovers/config_validator/error_processor.rb +196 -0
  32. data/lib/leftovers/config_validator/schema_hash.rb +495 -0
  33. data/lib/leftovers/definition.rb +11 -36
  34. data/lib/leftovers/definition_set.rb +7 -17
  35. data/lib/leftovers/dynamic_processors.rb +11 -0
  36. data/lib/leftovers/dynamic_processors/call.rb +25 -0
  37. data/lib/leftovers/dynamic_processors/call_definition.rb +31 -0
  38. data/lib/leftovers/dynamic_processors/definition.rb +26 -0
  39. data/lib/leftovers/dynamic_processors/each.rb +19 -0
  40. data/lib/leftovers/dynamic_processors/null.rb +9 -0
  41. data/lib/leftovers/erb.rb +2 -2
  42. data/lib/leftovers/file.rb +3 -5
  43. data/lib/leftovers/file_collector.rb +65 -49
  44. data/lib/leftovers/file_list.rb +0 -1
  45. data/lib/leftovers/haml.rb +1 -1
  46. data/lib/leftovers/matcher_builders.rb +24 -0
  47. data/lib/leftovers/matcher_builders/and.rb +19 -0
  48. data/lib/leftovers/matcher_builders/and_not.rb +14 -0
  49. data/lib/leftovers/matcher_builders/argument_node_value.rb +21 -0
  50. data/lib/leftovers/matcher_builders/name.rb +29 -0
  51. data/lib/leftovers/matcher_builders/node.rb +40 -0
  52. data/lib/leftovers/matcher_builders/node_has_argument.rb +71 -0
  53. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +22 -0
  54. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +24 -0
  55. data/lib/leftovers/matcher_builders/node_name.rb +15 -0
  56. data/lib/leftovers/matcher_builders/node_pair_name.rb +18 -0
  57. data/lib/leftovers/matcher_builders/node_pair_value.rb +16 -0
  58. data/lib/leftovers/matcher_builders/node_path.rb +14 -0
  59. data/lib/leftovers/matcher_builders/node_type.rb +28 -0
  60. data/lib/leftovers/matcher_builders/or.rb +73 -0
  61. data/lib/leftovers/matcher_builders/path.rb +15 -0
  62. data/lib/leftovers/matcher_builders/string.rb +11 -0
  63. data/lib/leftovers/matcher_builders/string_pattern.rb +19 -0
  64. data/lib/leftovers/matcher_builders/unless.rb +13 -0
  65. data/lib/leftovers/matchers.rb +26 -0
  66. data/lib/leftovers/matchers/all.rb +25 -0
  67. data/lib/leftovers/matchers/and.rb +24 -0
  68. data/lib/leftovers/matchers/any.rb +27 -0
  69. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +28 -0
  70. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +25 -0
  71. data/lib/leftovers/matchers/node_has_positional_argument.rb +23 -0
  72. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +25 -0
  73. data/lib/leftovers/matchers/node_name.rb +23 -0
  74. data/lib/leftovers/matchers/node_pair_value.rb +23 -0
  75. data/lib/leftovers/matchers/node_path.rb +23 -0
  76. data/lib/leftovers/matchers/node_scalar_value.rb +25 -0
  77. data/lib/leftovers/matchers/node_type.rb +23 -0
  78. data/lib/leftovers/matchers/not.rb +23 -0
  79. data/lib/leftovers/matchers/or.rb +26 -0
  80. data/lib/leftovers/merged_config.rb +13 -8
  81. data/lib/leftovers/parser.rb +1 -4
  82. data/lib/leftovers/processor_builders.rb +22 -0
  83. data/lib/leftovers/processor_builders/action.rb +63 -0
  84. data/lib/leftovers/processor_builders/add_prefix.rb +20 -0
  85. data/lib/leftovers/processor_builders/add_suffix.rb +20 -0
  86. data/lib/leftovers/processor_builders/argument.rb +25 -0
  87. data/lib/leftovers/processor_builders/dynamic.rb +27 -0
  88. data/lib/leftovers/processor_builders/each.rb +36 -0
  89. data/lib/leftovers/processor_builders/each_action.rb +51 -0
  90. data/lib/leftovers/processor_builders/each_dynamic.rb +54 -0
  91. data/lib/leftovers/processor_builders/each_for_definition_set.rb +36 -0
  92. data/lib/leftovers/processor_builders/itself.rb +13 -0
  93. data/lib/leftovers/processor_builders/keyword.rb +24 -0
  94. data/lib/leftovers/processor_builders/keyword_argument.rb +14 -0
  95. data/lib/leftovers/processor_builders/transform.rb +55 -0
  96. data/lib/leftovers/processor_builders/transform_chain.rb +24 -0
  97. data/lib/leftovers/processor_builders/transform_set.rb +47 -0
  98. data/lib/leftovers/processor_builders/value.rb +13 -0
  99. data/lib/leftovers/rake_task.rb +1 -1
  100. data/lib/leftovers/reporter.rb +1 -1
  101. data/lib/leftovers/value_processors.rb +40 -0
  102. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +31 -0
  103. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +31 -0
  104. data/lib/leftovers/value_processors/add_prefix.rb +20 -0
  105. data/lib/leftovers/value_processors/add_suffix.rb +20 -0
  106. data/lib/leftovers/value_processors/camelize.rb +24 -0
  107. data/lib/leftovers/value_processors/capitalize.rb +19 -0
  108. data/lib/leftovers/value_processors/deconstantize.rb +24 -0
  109. data/lib/leftovers/value_processors/delete_after.rb +22 -0
  110. data/lib/leftovers/value_processors/delete_before.rb +22 -0
  111. data/lib/leftovers/value_processors/delete_prefix.rb +26 -0
  112. data/lib/leftovers/value_processors/delete_suffix.rb +26 -0
  113. data/lib/leftovers/value_processors/demodulize.rb +24 -0
  114. data/lib/leftovers/value_processors/downcase.rb +19 -0
  115. data/lib/leftovers/value_processors/each.rb +21 -0
  116. data/lib/leftovers/value_processors/each_for_definition_set.rb +33 -0
  117. data/lib/leftovers/value_processors/each_keyword.rb +27 -0
  118. data/lib/leftovers/value_processors/each_keyword_argument.rb +27 -0
  119. data/lib/leftovers/value_processors/each_positional_argument.rb +24 -0
  120. data/lib/leftovers/value_processors/itself.rb +17 -0
  121. data/lib/leftovers/value_processors/keyword.rb +36 -0
  122. data/lib/leftovers/value_processors/keyword_argument.rb +36 -0
  123. data/lib/leftovers/value_processors/parameterize.rb +24 -0
  124. data/lib/leftovers/value_processors/placeholder.rb +18 -0
  125. data/lib/leftovers/value_processors/pluralize.rb +24 -0
  126. data/lib/leftovers/value_processors/positional_argument.rb +26 -0
  127. data/lib/leftovers/value_processors/replace_value.rb +18 -0
  128. data/lib/leftovers/value_processors/return_definition.rb +24 -0
  129. data/lib/leftovers/value_processors/return_string.rb +14 -0
  130. data/lib/leftovers/value_processors/singularize.rb +24 -0
  131. data/lib/leftovers/value_processors/split.rb +22 -0
  132. data/lib/leftovers/value_processors/swapcase.rb +19 -0
  133. data/lib/leftovers/value_processors/titleize.rb +24 -0
  134. data/lib/leftovers/value_processors/underscore.rb +24 -0
  135. data/lib/leftovers/value_processors/upcase.rb +19 -0
  136. data/lib/leftovers/version.rb +1 -1
  137. metadata +143 -24
  138. data/lib/leftovers/argument_rule.rb +0 -229
  139. data/lib/leftovers/core_ext.rb +0 -15
  140. data/lib/leftovers/hash_rule.rb +0 -42
  141. data/lib/leftovers/name_rule.rb +0 -98
  142. data/lib/leftovers/rule.rb +0 -82
  143. data/lib/leftovers/transform_rule.rb +0 -169
  144. data/lib/leftovers/value_rule.rb +0 -57
@@ -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
- attr_reader :test
7
+
8
8
  alias_method :test?, :test
9
9
 
10
10
  def initialize(
11
11
  name,
12
12
  method_node: nil,
13
13
  location: method_node.loc.expression,
14
- file: method_node.file,
15
14
  test: method_node.test?
16
15
  )
17
16
  @name = name
18
-
19
- @location = location
20
- @file = file
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
21
22
  @test = test
22
23
 
23
24
  freeze
24
25
  end
25
26
 
26
- def <=>(other)
27
- (path <=> other.path).nonzero? ||
28
- (line <=> other.line).nonzero? ||
29
- (column <=> other.column)
30
- end
31
-
32
- def path
33
- @file.relative_path
34
- end
35
-
36
27
  def to_s
37
28
  @name.to_s
38
29
  end
39
30
 
40
- def line
41
- @location.line
42
- end
43
-
44
- def column
45
- @location.column
46
- end
47
-
48
- def full_location
49
- "#{path}:#{line}:#{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, path) }
68
- end
69
44
  end
70
45
  end
@@ -1,24 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'definition'
4
3
  module Leftovers
5
- class DefinitionSet < Leftovers::Definition
6
- def initialize( # rubocop:disable Metrics/MethodLength
7
- names,
4
+ class DefinitionSet < ::Leftovers::Definition
5
+ attr_reader :definitions
6
+
7
+ def initialize(
8
+ definitions,
8
9
  method_node: nil,
9
10
  location: method_node.loc.expression,
10
- file: method_node.file,
11
11
  test: method_node.test?
12
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
13
+ @definitions = definitions
20
14
 
21
- freeze
15
+ super
22
16
  end
23
17
 
24
18
  def names
@@ -36,9 +30,5 @@ module Leftovers
36
30
  def in_test_collection?
37
31
  @definitions.any?(&:in_test_collection?)
38
32
  end
39
-
40
- def skipped?
41
- @definitions.any?(&:skipped?)
42
- end
43
33
  end
44
34
  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
@@ -0,0 +1,9 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module DynamicProcessors
5
+ module Null
6
+ def self.process(_node, _file); end
7
+ end
8
+ end
9
+ end
@@ -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
@@ -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 # rubocop:disable Metrics/MethodLength
17
+ def ruby
20
18
  case extname
21
19
  when '.haml'
22
- Leftovers::Haml.precompile(read, self)
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
- require_relative 'parser'
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 Metrics/MethodLength
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
47
  rescue ::Parser::SyntaxError => e
39
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[\?!=]?/.freeze
51
+ METHOD_NAME_RE = /[[:alpha:]_][[:alnum:]_]*\b[?!=]?/.freeze
43
52
  NON_ALNUM_METHOD_NAME_RE = Regexp.union(%w{
44
53
  []= [] ** ~ +@ -@ * / % + - >> << &
45
54
  ^ | <=> <= >= < > === == != =~ !~ !
@@ -49,7 +58,7 @@ module Leftovers
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
60
  LEFTOVERS_TEST_RE = /\bleftovers:(?:for_tests?|tests?|testing)\b/.freeze
52
- def process_comments(comments) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
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
64
  @test_lines << comment.loc.line if comment.text.match?(LEFTOVERS_TEST_RE)
@@ -62,66 +71,74 @@ module Leftovers
62
71
 
63
72
  # grab method definitions
64
73
  def on_def(node)
65
- add_definition(node.name, node.loc.name)
66
-
74
+ add_definition(node)
67
75
  super
68
76
  end
69
77
 
70
78
  def on_ivasgn(node)
71
- add_definition(node.name, node.loc.name)
79
+ collect_variable_assign(node)
80
+ super
81
+ end
72
82
 
73
- collect_rules(node)
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
94
  add_call(node.name)
95
+ super
96
+ end
82
97
 
98
+ def on_gvar(node)
99
+ add_call(node.name)
100
+ super
101
+ end
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
- add_call(node.name)
111
- collect_rules(node)
129
+ def on_csend(node)
130
+ super
131
+ collect_send(node)
112
132
  end
113
- alias_method :on_csend, :on_send
114
133
 
115
134
  def on_const(node)
116
135
  super
117
-
118
136
  add_call(node.name)
119
137
  end
120
138
 
121
139
  # grab e.g. :to_s in each(&:to_s)
122
140
  def on_block_pass(node)
123
141
  super
124
-
125
142
  add_call(node.children.first.to_sym) if node.children.first.string_or_symbol?
126
143
  end
127
144
 
@@ -133,26 +150,22 @@ module Leftovers
133
150
 
134
151
  node = node.children.first
135
152
 
136
- add_definition(node.name, node.loc.name)
153
+ add_definition(node)
137
154
  end
138
155
  alias_method :on_module, :on_class
139
156
 
140
157
  # grab Constant = Class.new or CONSTANT = 'string'.freeze
141
158
  def on_casgn(node)
142
159
  super
143
-
144
- add_definition(node.name, node.loc.name)
145
-
146
- collect_rules(node)
160
+ add_definition(node)
161
+ collect_dynamic(node)
147
162
  end
148
163
 
149
164
  # grab calls to `alias new_method original_method`
150
165
  def on_alias(node)
151
166
  super
152
-
153
167
  new_method, original_method = node.children
154
-
155
- 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)
156
169
  add_call(original_method.children.first)
157
170
  end
158
171
 
@@ -162,16 +175,22 @@ module Leftovers
162
175
  @file.test? || @test_lines.include?(loc.line)
163
176
  end
164
177
 
165
- def add_definition(name, loc)
178
+ def add_definition(node, name: node.name, loc: node.loc.name)
166
179
  return if @allow_lines.include?(loc.line)
180
+ return if Leftovers.config.keep === node
167
181
 
168
- definitions << Leftovers::Definition.new(name, location: loc, file: @file, test: test?(loc))
182
+ definitions << Leftovers::Definition.new(name, location: loc, test: test?(loc))
169
183
  end
170
184
 
171
185
  def add_call(name)
172
186
  calls << name
173
187
  end
174
188
 
189
+ def collect_send(node)
190
+ add_call(node.name)
191
+ collect_dynamic(node)
192
+ end
193
+
175
194
  # just collects the call, super will collect the definition
176
195
  def collect_var_op_asgn(node)
177
196
  name = node.children.first
@@ -185,6 +204,12 @@ module Leftovers
185
204
  add_call(:"#{name}=")
186
205
  end
187
206
 
207
+ def collect_variable_assign(node)
208
+ add_definition(node)
209
+
210
+ collect_dynamic(node)
211
+ end
212
+
188
213
  def collect_op_asgn(node)
189
214
  node = node.children.first
190
215
  # :nocov: # don't need else, it's exhaustive for callers
@@ -195,22 +220,13 @@ module Leftovers
195
220
  end
196
221
  end
197
222
 
198
- def collect_rules(node) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
199
- Leftovers.config.rules.each do |rule|
200
- next unless rule.match?(node.name, filename)
223
+ def collect_dynamic(node) # rubocop:disable Metrics/AbcSize
224
+ node.keep_line = @allow_lines.include?(node.loc.line)
225
+ node.test = test?(node.loc) unless node.keep_line?
201
226
 
202
- next if rule.skip?
203
-
204
- calls.concat(rule.calls(node))
205
-
206
- next if @allow_lines.include?(node.loc.line)
207
-
208
- node.file = @file
209
- node.test = test?(node.loc)
210
- definitions.concat(rule.definitions(node))
211
- end
227
+ Leftovers.config.dynamic.process(node, self)
212
228
  rescue StandardError => e
213
- raise e.class, "#{e.message}\nwhen processing #{node} at #{filename}:#{node.loc.line}:#{node.loc.column}", e.backtrace # rubocop:disable Layout/LineLength
229
+ raise ::Leftovers::Error, "#{e.class}: #{e.message}\nwhen processing #{node} at #{filename}:#{node.loc.line}:#{node.loc.column}", e.backtrace # rubocop:disable Layout/LineLength
214
230
  end
215
231
  end
216
232
  end