leftovers 0.3.0 → 0.4.0

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