leftovers 0.8.0 → 0.9.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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/README.md +7 -7
  4. data/docs/Configuration.md +141 -32
  5. data/docs/Custom-Precompilers.md +6 -0
  6. data/leftovers.gemspec +2 -1
  7. data/lib/config/actioncable.yml +36 -0
  8. data/lib/config/actionmailbox.yml +28 -0
  9. data/lib/config/actionmailer.yml +87 -11
  10. data/lib/config/actionpack.yml +130 -34
  11. data/lib/config/actiontext.yml +56 -0
  12. data/lib/config/actionview.yml +194 -44
  13. data/lib/config/activejob.yml +15 -8
  14. data/lib/config/activemodel.yml +175 -18
  15. data/lib/config/activerecord.yml +397 -86
  16. data/lib/config/activestorage.yml +26 -0
  17. data/lib/config/activesupport.yml +167 -24
  18. data/lib/config/leftovers.yml +48 -0
  19. data/lib/config/rails.yml +7 -3
  20. data/lib/config/railties.yml +7 -0
  21. data/lib/config/ruby.yml +438 -83
  22. data/lib/config/test-unit.yml +8 -0
  23. data/lib/leftovers/ast/array_node.rb +12 -0
  24. data/lib/leftovers/ast/block_node.rb +12 -0
  25. data/lib/leftovers/ast/builder.rb +24 -5
  26. data/lib/leftovers/ast/casgn_node.rb +20 -0
  27. data/lib/leftovers/ast/const_node.rb +15 -0
  28. data/lib/leftovers/ast/def_node.rb +15 -0
  29. data/lib/leftovers/ast/defs_node.rb +15 -0
  30. data/lib/leftovers/ast/false_node.rb +24 -0
  31. data/lib/leftovers/ast/has_arguments.rb +31 -0
  32. data/lib/leftovers/ast/hash_node.rb +17 -0
  33. data/lib/leftovers/ast/module_node.rb +16 -0
  34. data/lib/leftovers/ast/nil_node.rb +23 -0
  35. data/lib/leftovers/ast/node.rb +33 -90
  36. data/lib/leftovers/ast/numeric_node.rb +22 -0
  37. data/lib/leftovers/ast/send_node.rb +25 -0
  38. data/lib/leftovers/ast/str_node.rb +24 -0
  39. data/lib/leftovers/ast/sym_node.rb +25 -0
  40. data/lib/leftovers/ast/true_node.rb +24 -0
  41. data/lib/leftovers/ast/var_node.rb +14 -0
  42. data/lib/leftovers/ast/vasgn_node.rb +20 -0
  43. data/lib/leftovers/ast.rb +18 -0
  44. data/lib/leftovers/cli.rb +7 -1
  45. data/lib/leftovers/comparable_instance.rb +18 -0
  46. data/lib/leftovers/config_loader/argument_position_schema.rb +3 -1
  47. data/lib/leftovers/config_loader/array_schema.rb +53 -0
  48. data/lib/leftovers/config_loader/document_schema.rb +3 -2
  49. data/lib/leftovers/config_loader/dynamic_schema.rb +1 -0
  50. data/lib/leftovers/config_loader/has_value_schema.rb +4 -0
  51. data/lib/leftovers/config_loader/keyword_argument_schema.rb +13 -0
  52. data/lib/leftovers/config_loader/regexp_schema.rb +27 -0
  53. data/lib/leftovers/config_loader/rule_pattern_schema.rb +2 -0
  54. data/lib/leftovers/config_loader/scalar_value_schema.rb +8 -0
  55. data/lib/leftovers/config_loader/schema.rb +10 -0
  56. data/lib/leftovers/config_loader/string_enum_schema.rb +1 -1
  57. data/lib/leftovers/config_loader/string_pattern_schema.rb +1 -1
  58. data/lib/leftovers/config_loader/transform_schema.rb +12 -6
  59. data/lib/leftovers/config_loader/value_matcher_condition_schema.rb +13 -0
  60. data/lib/leftovers/config_loader/value_matcher_schema.rb +4 -1
  61. data/lib/leftovers/config_loader/value_or_array_schema.rb +2 -34
  62. data/lib/leftovers/config_loader/value_processor_schema.rb +2 -2
  63. data/lib/leftovers/config_loader.rb +11 -4
  64. data/lib/leftovers/definition_collection.rb +37 -0
  65. data/lib/leftovers/definition_node_set.rb +10 -2
  66. data/lib/leftovers/file.rb +1 -1
  67. data/lib/leftovers/file_collector/comments_processor.rb +1 -1
  68. data/lib/leftovers/file_collector/node_processor.rb +7 -7
  69. data/lib/leftovers/file_collector.rb +26 -32
  70. data/lib/leftovers/file_list.rb +3 -2
  71. data/lib/leftovers/matcher_builders/and.rb +26 -9
  72. data/lib/leftovers/matcher_builders/node.rb +32 -20
  73. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +3 -1
  74. data/lib/leftovers/matcher_builders/node_pair_key.rb +16 -0
  75. data/lib/leftovers/matcher_builders/node_type.rb +9 -9
  76. data/lib/leftovers/matcher_builders/node_value.rb +23 -9
  77. data/lib/leftovers/matcher_builders/or.rb +22 -7
  78. data/lib/leftovers/matcher_builders/path.rb +3 -1
  79. data/lib/leftovers/matcher_builders.rb +1 -1
  80. data/lib/leftovers/matchers/all.rb +4 -0
  81. data/lib/leftovers/matchers/and.rb +4 -0
  82. data/lib/leftovers/matchers/any.rb +2 -0
  83. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +7 -4
  84. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +5 -4
  85. data/lib/leftovers/matchers/node_has_positional_argument.rb +5 -1
  86. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +6 -1
  87. data/lib/leftovers/matchers/node_has_receiver.rb +4 -0
  88. data/lib/leftovers/matchers/node_is_proc.rb +13 -0
  89. data/lib/leftovers/matchers/node_name.rb +9 -3
  90. data/lib/leftovers/matchers/node_pair_key.rb +23 -0
  91. data/lib/leftovers/matchers/node_pair_value.rb +7 -3
  92. data/lib/leftovers/matchers/node_path.rb +7 -3
  93. data/lib/leftovers/matchers/node_privacy.rb +7 -3
  94. data/lib/leftovers/matchers/node_scalar_value.rb +6 -1
  95. data/lib/leftovers/matchers/node_type.rb +7 -3
  96. data/lib/leftovers/matchers/not.rb +2 -0
  97. data/lib/leftovers/matchers/or.rb +2 -0
  98. data/lib/leftovers/matchers/path.rb +21 -0
  99. data/lib/leftovers/matchers.rb +3 -1
  100. data/lib/leftovers/merged_config.rb +26 -25
  101. data/lib/leftovers/parser.rb +7 -4
  102. data/lib/leftovers/precompilers.rb +5 -5
  103. data/lib/leftovers/processor_builders/action.rb +55 -37
  104. data/lib/leftovers/processor_builders/add_prefix.rb +18 -10
  105. data/lib/leftovers/processor_builders/add_suffix.rb +18 -10
  106. data/lib/leftovers/processor_builders/argument.rb +28 -11
  107. data/lib/leftovers/processor_builders/dynamic.rb +37 -31
  108. data/lib/leftovers/processor_builders/each.rb +82 -10
  109. data/lib/leftovers/processor_builders/itself.rb +2 -2
  110. data/lib/leftovers/processor_builders/keyword.rb +7 -6
  111. data/lib/leftovers/processor_builders/keyword_argument.rb +4 -2
  112. data/lib/leftovers/processor_builders/receiver.rb +13 -0
  113. data/lib/leftovers/processor_builders/transform.rb +55 -44
  114. data/lib/leftovers/processor_builders/transform_chain.rb +1 -1
  115. data/lib/leftovers/processor_builders/transform_set.rb +9 -29
  116. data/lib/leftovers/processor_builders/value.rb +4 -4
  117. data/lib/leftovers/processor_builders.rb +1 -3
  118. data/lib/leftovers/processors/add_call.rb +14 -0
  119. data/lib/leftovers/processors/add_definition_node.rb +16 -0
  120. data/lib/leftovers/processors/add_dynamic_prefix.rb +29 -0
  121. data/lib/leftovers/processors/add_dynamic_suffix.rb +29 -0
  122. data/lib/leftovers/{value_processors → processors}/add_prefix.rb +7 -3
  123. data/lib/leftovers/{value_processors → processors}/add_suffix.rb +7 -3
  124. data/lib/leftovers/processors/append_sym.rb +13 -0
  125. data/lib/leftovers/{value_processors → processors}/camelize.rb +7 -3
  126. data/lib/leftovers/{value_processors → processors}/capitalize.rb +7 -3
  127. data/lib/leftovers/{value_processors → processors}/deconstantize.rb +7 -3
  128. data/lib/leftovers/{value_processors → processors}/delete_after.rb +9 -5
  129. data/lib/leftovers/processors/delete_after_last.rb +26 -0
  130. data/lib/leftovers/processors/delete_before.rb +27 -0
  131. data/lib/leftovers/processors/delete_before_last.rb +27 -0
  132. data/lib/leftovers/{value_processors → processors}/delete_prefix.rb +7 -3
  133. data/lib/leftovers/{value_processors → processors}/delete_suffix.rb +7 -3
  134. data/lib/leftovers/{value_processors → processors}/demodulize.rb +7 -3
  135. data/lib/leftovers/{value_processors → processors}/downcase.rb +7 -3
  136. data/lib/leftovers/processors/each.rb +25 -0
  137. data/lib/leftovers/processors/each_for_definition_set.rb +33 -0
  138. data/lib/leftovers/processors/each_keyword.rb +29 -0
  139. data/lib/leftovers/processors/each_keyword_argument.rb +29 -0
  140. data/lib/leftovers/processors/each_positional_argument.rb +27 -0
  141. data/lib/leftovers/processors/each_positional_argument_from.rb +30 -0
  142. data/lib/leftovers/processors/eval.rb +16 -0
  143. data/lib/leftovers/processors/itself.rb +21 -0
  144. data/lib/leftovers/processors/keyword_argument.rb +30 -0
  145. data/lib/leftovers/processors/match_current_node.rb +26 -0
  146. data/lib/leftovers/processors/match_matched_node.rb +26 -0
  147. data/lib/leftovers/{value_processors → processors}/parameterize.rb +7 -3
  148. data/lib/leftovers/{value_processors → processors}/placeholder.rb +5 -4
  149. data/lib/leftovers/{value_processors → processors}/pluralize.rb +7 -3
  150. data/lib/leftovers/{value_processors → processors}/positional_argument.rb +8 -6
  151. data/lib/leftovers/processors/receiver.rb +24 -0
  152. data/lib/leftovers/{value_processors → processors}/replace_value.rb +7 -3
  153. data/lib/leftovers/processors/set_default_privacy.rb +21 -0
  154. data/lib/leftovers/processors/set_privacy.rb +23 -0
  155. data/lib/leftovers/{value_processors → processors}/singularize.rb +7 -3
  156. data/lib/leftovers/{value_processors → processors}/split.rb +8 -4
  157. data/lib/leftovers/{value_processors → processors}/swapcase.rb +7 -3
  158. data/lib/leftovers/{value_processors → processors}/titleize.rb +7 -3
  159. data/lib/leftovers/{value_processors → processors}/underscore.rb +7 -3
  160. data/lib/leftovers/{value_processors → processors}/upcase.rb +7 -3
  161. data/lib/leftovers/processors.rb +49 -0
  162. data/lib/leftovers/version.rb +1 -1
  163. data/lib/leftovers.rb +3 -12
  164. metadata +97 -52
  165. data/lib/leftovers/dynamic_processors/call.rb +0 -22
  166. data/lib/leftovers/dynamic_processors/call_definition.rb +0 -34
  167. data/lib/leftovers/dynamic_processors/definition.rb +0 -27
  168. data/lib/leftovers/dynamic_processors/each.rb +0 -19
  169. data/lib/leftovers/dynamic_processors/null.rb +0 -9
  170. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +0 -18
  171. data/lib/leftovers/dynamic_processors/set_privacy.rb +0 -23
  172. data/lib/leftovers/dynamic_processors.rb +0 -13
  173. data/lib/leftovers/matcher_builders/node_pair_name.rb +0 -18
  174. data/lib/leftovers/matchers/predicate.rb +0 -19
  175. data/lib/leftovers/processor_builders/each_action.rb +0 -51
  176. data/lib/leftovers/processor_builders/each_dynamic.rb +0 -50
  177. data/lib/leftovers/processor_builders/each_for_definition_set.rb +0 -40
  178. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +0 -24
  179. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +0 -24
  180. data/lib/leftovers/value_processors/delete_before.rb +0 -22
  181. data/lib/leftovers/value_processors/each.rb +0 -21
  182. data/lib/leftovers/value_processors/each_for_definition_set.rb +0 -23
  183. data/lib/leftovers/value_processors/each_keyword.rb +0 -27
  184. data/lib/leftovers/value_processors/each_keyword_argument.rb +0 -27
  185. data/lib/leftovers/value_processors/each_positional_argument.rb +0 -25
  186. data/lib/leftovers/value_processors/itself.rb +0 -17
  187. data/lib/leftovers/value_processors/keyword.rb +0 -28
  188. data/lib/leftovers/value_processors/keyword_argument.rb +0 -28
  189. data/lib/leftovers/value_processors/return_definition_node.rb +0 -14
  190. data/lib/leftovers/value_processors/return_sym.rb +0 -14
  191. data/lib/leftovers/value_processors.rb +0 -40
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class RegexpSchema < StringSchema
6
+ class << self
7
+ def validate(node)
8
+ validate_string(node) && validate_regexp(node)
9
+ end
10
+
11
+ def validate_string(node)
12
+ error(node, 'be a string with a valid ruby regexp') unless node.string?
13
+
14
+ node.valid?
15
+ end
16
+
17
+ def validate_regexp(node)
18
+ /#{node.to_ruby}/
19
+ rescue RegexpError, ArgumentError => e
20
+ error(node, "be a string with a valid ruby regexp (#{e.message})")
21
+ else
22
+ true
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -13,6 +13,8 @@ module Leftovers
13
13
  attribute :type, ValueOrArraySchema[ValueTypeSchema], require_group: :matcher
14
14
  attribute :privacy, ValueOrArraySchema[PrivacySchema], require_group: :matcher
15
15
  attribute :unless, ValueOrArraySchema[RulePatternSchema], require_group: :matcher
16
+ attribute :all, ArraySchema[RulePatternSchema], require_group: :matcher
17
+ attribute :any, ArraySchema[RulePatternSchema], require_group: :matcher
16
18
  end
17
19
  end
18
20
  end
@@ -8,6 +8,14 @@ module Leftovers
8
8
  error(node, 'be any scalar value') unless node.scalar?
9
9
  super
10
10
  end
11
+
12
+ def to_ruby(node)
13
+ if node.to_ruby.nil?
14
+ :_leftovers_nil_value
15
+ else
16
+ node.to_ruby
17
+ end
18
+ end
11
19
  end
12
20
  end
13
21
  end
@@ -17,6 +17,16 @@ module Leftovers
17
17
  def to_ruby(node)
18
18
  node.to_ruby
19
19
  end
20
+
21
+ def ===(other) # leftovers:test_only
22
+ # :nocov:
23
+ if other.is_a?(Module)
24
+ self >= other
25
+ else
26
+ other.is_a?(self)
27
+ end
28
+ # :nocov:
29
+ end
20
30
  end
21
31
  end
22
32
  end
@@ -28,7 +28,7 @@ module Leftovers
28
28
  end
29
29
 
30
30
  def to_ruby(node)
31
- aliases[node.to_sym]&.to_s || node.to_ruby
31
+ aliases[node.to_sym] || node.to_sym
32
32
  end
33
33
 
34
34
  def validate(node)
@@ -3,7 +3,7 @@
3
3
  module Leftovers
4
4
  class ConfigLoader
5
5
  class StringPatternSchema < ValueOrObjectSchema
6
- attribute :match, StringSchema, aliases: :matches, require_group: :matcher
6
+ attribute :match, RegexpSchema, aliases: :matches, require_group: :matcher
7
7
  attribute :has_prefix, StringSchema, require_group: :matcher
8
8
  attribute :has_suffix, StringSchema, require_group: :matcher
9
9
  attribute :unless, ValueOrArraySchema[StringPatternSchema], require_group: :matcher
@@ -11,14 +11,20 @@ module Leftovers
11
11
  )
12
12
  end
13
13
 
14
- attribute :add_prefix, StringValueProcessorSchema, require_group: :processor
15
- attribute :add_suffix, StringValueProcessorSchema, require_group: :processor
14
+ attribute :add_prefix, ValueOrArraySchema[StringValueProcessorSchema],
15
+ require_group: :processor
16
+ attribute :add_suffix, ValueOrArraySchema[StringValueProcessorSchema],
17
+ require_group: :processor
16
18
 
17
19
  attribute :split, StringSchema, require_group: :processor
18
- attribute :delete_prefix, StringSchema, require_group: :processor
19
- attribute :delete_suffix, StringSchema, require_group: :processor
20
- attribute :delete_before, StringSchema, require_group: :processor
21
- attribute :delete_after, StringSchema, require_group: :processor
20
+ attribute :delete_prefix, ValueOrArraySchema[StringSchema], require_group: :processor
21
+ attribute :delete_suffix, ValueOrArraySchema[StringSchema], require_group: :processor
22
+ attribute :delete_before, ValueOrArraySchema[StringSchema], require_group: :processor
23
+ attribute :delete_before_last, ValueOrArraySchema[StringSchema], require_group: :processor
24
+ attribute :delete_after, ValueOrArraySchema[StringSchema], require_group: :processor
25
+ attribute :delete_after_last, ValueOrArraySchema[StringSchema], require_group: :processor
26
+ attribute :transforms, ValueOrArraySchema[TransformSchema], require_group: :processor,
27
+ aliases: :transform
22
28
 
23
29
  self.or_value_schema = ArgumentlessTransformSchema
24
30
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ValueMatcherConditionSchema < ObjectSchema
6
+ attribute :has_arguments, ValueOrArraySchema[HasArgumentSchema], aliases: :has_argument
7
+ attribute :has_receiver, ValueOrArraySchema[HasValueSchema]
8
+ attribute :unless, ValueOrArraySchema[ValueMatcherConditionSchema]
9
+ attribute :all, ArraySchema[ValueMatcherConditionSchema]
10
+ attribute :any, ArraySchema[ValueMatcherConditionSchema]
11
+ end
12
+ end
13
+ end
@@ -9,9 +9,12 @@ module Leftovers
9
9
  require_group: :matcher
10
10
  attribute :itself, TrueSchema, require_group: :matcher
11
11
  attribute :nested, ValueOrArraySchema[ValueMatcherSchema]
12
- attribute :value, StringSchema, require_group: :matcher
12
+ attribute :value, ValueOrArraySchema[StringSchema], require_group: :matcher, aliases: :values
13
+ attribute :receiver, TrueSchema, require_group: :matcher
13
14
  attribute :recursive, TrueSchema
14
15
 
16
+ inherit_attributes_from ValueMatcherConditionSchema
17
+
15
18
  self.or_value_schema = ScalarArgumentSchema
16
19
  end
17
20
  end
@@ -2,21 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  class ConfigLoader
5
- class ValueOrArraySchema < Schema
6
- class << self
7
- def [](value_schema)
8
- new(value_schema)
9
- end
10
- end
11
-
12
- attr_reader :value_schema
13
-
14
- def initialize(value_schema)
15
- @value_schema = value_schema
16
-
17
- super()
18
- end
19
-
5
+ class ValueOrArraySchema < ArraySchema
20
6
  def validate(node)
21
7
  if node.array?
22
8
  validate_length(node) && validate_values(node)
@@ -27,11 +13,7 @@ module Leftovers
27
13
 
28
14
  def to_ruby(node)
29
15
  if node.array?
30
- Leftovers.unwrap_array(
31
- node.children.map do |value|
32
- value_schema.to_ruby(value)
33
- end
34
- )
16
+ Leftovers.unwrap_array(super)
35
17
  else
36
18
  value_schema.to_ruby(node)
37
19
  end
@@ -47,20 +29,6 @@ module Leftovers
47
29
 
48
30
  false
49
31
  end
50
-
51
- def validate_length(node)
52
- self.class.error(node, 'not be empty') if node.children.empty?
53
-
54
- node.valid?
55
- end
56
-
57
- def validate_values(node)
58
- node.children.each do |value|
59
- value_schema.validate(value)
60
- end
61
-
62
- node.children.all?(&:valid?)
63
- end
64
32
  end
65
33
  end
66
34
  end
@@ -5,8 +5,8 @@ module Leftovers
5
5
  class ValueProcessorSchema < ValueOrObjectSchema
6
6
  inherit_attributes_from ValueMatcherSchema
7
7
 
8
- attribute :transforms, ValueOrArraySchema[TransformSchema]
9
- inherit_attributes_from TransformSchema, require_group: nil
8
+ attribute :transforms, ValueOrArraySchema[TransformSchema], aliases: :transform
9
+ inherit_attributes_from TransformSchema, require_group: nil, except: :transforms
10
10
 
11
11
  self.or_value_schema = ScalarArgumentSchema
12
12
  end
@@ -4,34 +4,41 @@ require 'yaml'
4
4
 
5
5
  module Leftovers
6
6
  class ConfigLoader
7
- autoload(:ArgumentPositionSchema, "#{__dir__}/config_loader/argument_position_schema")
8
7
  autoload(:ArgumentlessTransformSchema, "#{__dir__}/config_loader/argumentless_transform_schema")
8
+ autoload(:ArgumentPositionSchema, "#{__dir__}/config_loader/argument_position_schema")
9
+ autoload(:ArraySchema, "#{__dir__}/config_loader/array_schema")
9
10
  autoload(:Attribute, "#{__dir__}/config_loader/attribute")
10
11
  autoload(:BuiltInPrecompilerSchema, "#{__dir__}/config_loader/built_in_precompiler_schema")
11
12
  autoload(:DocumentSchema, "#{__dir__}/config_loader/document_schema")
12
13
  autoload(:DynamicSchema, "#{__dir__}/config_loader/dynamic_schema")
13
- autoload(:InheritSchemaAttributes, "#{__dir__}/config_loader/inherit_schema_attributes")
14
14
  autoload(:HasArgumentSchema, "#{__dir__}/config_loader/has_argument_schema")
15
15
  autoload(:HasValueSchema, "#{__dir__}/config_loader/has_value_schema")
16
+ autoload(:InheritSchemaAttributes, "#{__dir__}/config_loader/inherit_schema_attributes")
16
17
  autoload(:KeepTestOnlySchema, "#{__dir__}/config_loader/keep_test_only_schema")
18
+ autoload(:KeywordArgumentSchema, "#{__dir__}/config_loader/keyword_argument_schema")
17
19
  autoload(:Node, "#{__dir__}/config_loader/node")
18
20
  autoload(:ObjectSchema, "#{__dir__}/config_loader/object_schema")
19
- autoload(:PrecompileSchema, "#{__dir__}/config_loader/precompile_schema")
20
21
  autoload(:PrecompilerSchema, "#{__dir__}/config_loader/precompiler_schema")
22
+ autoload(:PrecompileSchema, "#{__dir__}/config_loader/precompile_schema")
21
23
  autoload(:PrivacyProcessorSchema, "#{__dir__}/config_loader/privacy_processor_schema")
22
24
  autoload(:PrivacySchema, "#{__dir__}/config_loader/privacy_schema")
25
+ autoload(:RegexpSchema, "#{__dir__}/config_loader/regexp_schema")
23
26
  autoload(:RequireSchema, "#{__dir__}/config_loader/require_schema")
24
27
  autoload(:RulePatternSchema, "#{__dir__}/config_loader/rule_pattern_schema")
25
28
  autoload(:ScalarArgumentSchema, "#{__dir__}/config_loader/scalar_argument_schema")
26
29
  autoload(:ScalarValueSchema, "#{__dir__}/config_loader/scalar_value_schema")
27
30
  autoload(:Schema, "#{__dir__}/config_loader/schema")
28
- autoload(:Suggester, "#{__dir__}/config_loader/suggester")
29
31
  autoload(:StringEnumSchema, "#{__dir__}/config_loader/string_enum_schema")
30
32
  autoload(:StringPatternSchema, "#{__dir__}/config_loader/string_pattern_schema")
31
33
  autoload(:StringSchema, "#{__dir__}/config_loader/string_schema")
32
34
  autoload(:StringValueProcessorSchema, "#{__dir__}/config_loader/string_value_processor_schema")
35
+ autoload(:Suggester, "#{__dir__}/config_loader/suggester")
33
36
  autoload(:TransformSchema, "#{__dir__}/config_loader/transform_schema")
34
37
  autoload(:TrueSchema, "#{__dir__}/config_loader/true_schema")
38
+ autoload(
39
+ :ValueMatcherConditionSchema,
40
+ "#{__dir__}/config_loader/value_matcher_condition_schema"
41
+ )
35
42
  autoload(:ValueMatcherSchema, "#{__dir__}/config_loader/value_matcher_schema")
36
43
  autoload(:ValueOrArraySchema, "#{__dir__}/config_loader/value_or_array_schema")
37
44
  autoload(:ValueOrObjectSchema, "#{__dir__}/config_loader/value_or_object_schema")
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class DefinitionCollection
5
+ def initialize
6
+ @definitions_to_add = {}
7
+ @definition_sets_to_add = []
8
+ end
9
+
10
+ def add_definition_node(definition_node)
11
+ add(definition_node, loc: definition_node.loc)
12
+ end
13
+
14
+ def add(node, name: node.name, loc: node.loc.name)
15
+ @definitions_to_add[name] = ::Leftovers::DefinitionToAdd.new(node, name: name, location: loc)
16
+ end
17
+
18
+ def add_definition_set(definition_node_set)
19
+ @definition_sets_to_add << definition_node_set.definitions.map do |definition_node|
20
+ ::Leftovers::DefinitionToAdd.new(definition_node, location: definition_node.loc)
21
+ end
22
+ end
23
+
24
+ def set_privacy(name, to)
25
+ @definitions_to_add[name]&.privacy = to
26
+ end
27
+
28
+ def to_definitions(file_collector)
29
+ @definitions_to_add.each_value.map { |d| d.to_definition(file_collector) } +
30
+ @definition_sets_to_add.map do |definition_set|
31
+ next if definition_set.any? { |d| d.keep?(file_collector) }
32
+
33
+ ::Leftovers::DefinitionSet.new(definition_set.map { |d| d.to_definition(file_collector) })
34
+ end
35
+ end
36
+ end
37
+ end
@@ -4,8 +4,16 @@ module Leftovers
4
4
  class DefinitionNodeSet
5
5
  attr_reader :definitions
6
6
 
7
- def initialize(definitions)
8
- @definitions = definitions
7
+ def initialize
8
+ @definitions = []
9
+ end
10
+
11
+ def add_definition_node(definition_node)
12
+ @definitions << definition_node
13
+ end
14
+
15
+ def add_definition_set(definition_node_set)
16
+ @definitions.concat(definition_node_set.definitions)
9
17
  end
10
18
  end
11
19
  end
@@ -15,7 +15,7 @@ module Leftovers
15
15
  def test?
16
16
  return @test if defined?(@test)
17
17
 
18
- @test = Leftovers.config.test_paths.allowed?(relative_path)
18
+ @test = Leftovers.config.test_paths === relative_path
19
19
  end
20
20
 
21
21
  def ruby
@@ -49,7 +49,7 @@ module Leftovers
49
49
  match = comment.text.match(LEFTOVERS_CALL_RE)
50
50
  return unless match
51
51
 
52
- match[1].scan(NAME_RE).each { |s| collector.add_call(s.to_sym) }
52
+ match[1].scan(NAME_RE).each { |s| collector.calls << s.to_sym }
53
53
  end
54
54
  end
55
55
  end
@@ -36,17 +36,17 @@ module Leftovers
36
36
  end
37
37
 
38
38
  def on_ivar(node)
39
- @collector.add_call(node.name)
39
+ @collector.calls << node.name
40
40
  super
41
41
  end
42
42
 
43
43
  def on_gvar(node)
44
- @collector.add_call(node.name)
44
+ @collector.calls << node.name
45
45
  super
46
46
  end
47
47
 
48
48
  def on_cvar(node)
49
- @collector.add_call(node.name)
49
+ @collector.calls << node.name
50
50
  super
51
51
  end
52
52
 
@@ -77,7 +77,7 @@ module Leftovers
77
77
 
78
78
  def on_const(node)
79
79
  super
80
- @collector.add_call(node.name)
80
+ @collector.calls << node.name
81
81
  end
82
82
 
83
83
  def on_array(node)
@@ -93,9 +93,9 @@ module Leftovers
93
93
  # grab e.g. :to_s in each(&:to_s)
94
94
  def on_block_pass(node)
95
95
  super
96
- return unless node.first.string_or_symbol?
96
+ return unless node.first.sym?
97
97
 
98
- @collector.add_call(node.first.to_sym)
98
+ @collector.calls << node.first.to_sym
99
99
  end
100
100
 
101
101
  # grab class Constant or module Constant
@@ -124,7 +124,7 @@ module Leftovers
124
124
  @collector.add_definition(
125
125
  new_method, name: new_method.children.first, loc: new_method.loc.expression
126
126
  )
127
- @collector.add_call(original_method.children.first)
127
+ @collector.calls << original_method.children.first
128
128
  end
129
129
  end
130
130
  end
@@ -12,14 +12,13 @@ module Leftovers
12
12
 
13
13
  def initialize(ruby, file)
14
14
  @calls = []
15
- @definitions_to_add = {}
15
+ @definition_collection = Leftovers::DefinitionCollection.new
16
16
  @allow_lines = Set.new.compare_by_identity
17
17
  @test_lines = Set.new.compare_by_identity
18
18
  @dynamic_lines = {}
19
19
  @ruby = ruby
20
20
  @file = file
21
21
  @default_method_privacy = :public
22
- @definition_sets_to_add = []
23
22
  end
24
23
 
25
24
  def filename
@@ -37,8 +36,8 @@ module Leftovers
37
36
  list
38
37
  end
39
38
 
40
- def collect
41
- ast, comments = Leftovers::Parser.parse_with_comments(@ruby, @file.relative_path)
39
+ def collect(ruby = @ruby, line = 1)
40
+ ast, comments = Leftovers::Parser.parse_with_comments(ruby, @file.relative_path, line)
42
41
  CommentsProcessor.process(comments, self)
43
42
  NodeProcessor.new(self).process(ast)
44
43
  rescue ::Parser::SyntaxError => e
@@ -48,44 +47,41 @@ module Leftovers
48
47
  )
49
48
  end
50
49
 
51
- # grab method definitions
52
- def add_definition(node, name: node.name, loc: node.loc.name)
53
- @definitions_to_add[name] = ::Leftovers::DefinitionToAdd.new(node, name: name, location: loc)
50
+ def collect_subfile(string, location)
51
+ string = (' ' * location.column) + string # match indentation
52
+ collect(string, location.line)
54
53
  end
55
54
 
56
- def add_definition_set(definition_node_set)
57
- @definition_sets_to_add << definition_node_set.definitions.map do |definition_node|
58
- ::Leftovers::DefinitionToAdd.new(definition_node, location: definition_node.loc)
59
- end
55
+ def test_line?(line)
56
+ @file.test? || @test_lines.include?(line)
60
57
  end
61
58
 
62
- def set_privacy(name, to)
63
- @definitions_to_add[name]&.privacy = to
59
+ def keep_line?(line)
60
+ @allow_lines.include?(line)
64
61
  end
65
62
 
66
- def definitions
67
- @definitions ||= @definitions_to_add.each_value.map { |d| d.to_definition(self) } +
68
- @definition_sets_to_add.map do |definition_set|
69
- next if definition_set.any? { |d| d.keep?(self) }
63
+ def add_definition_set(definition_node_set)
64
+ @definition_collection.add_definition_set(definition_node_set)
65
+ end
70
66
 
71
- ::Leftovers::DefinitionSet.new(definition_set.map { |d| d.to_definition(self) })
72
- end
67
+ def set_privacy(node, to)
68
+ @definition_collection.set_privacy(node, to)
73
69
  end
74
70
 
75
- def test_line?(line)
76
- @file.test? || @test_lines.include?(line)
71
+ def add_definition(node, name: node.name, loc: node.loc.name)
72
+ @definition_collection.add(node, name: name, loc: loc)
77
73
  end
78
74
 
79
- def keep_line?(line)
80
- @allow_lines.include?(line)
75
+ def add_definition_node(definition_node)
76
+ @definition_collection.add_definition_node(definition_node)
81
77
  end
82
78
 
83
- def add_call(name)
84
- calls << name
79
+ def definitions
80
+ @definitions ||= @definition_collection.to_definitions(self)
85
81
  end
86
82
 
87
83
  def collect_send(node)
88
- add_call(node.name)
84
+ calls << node.name
89
85
  collect_dynamic(node)
90
86
  end
91
87
 
@@ -98,9 +94,9 @@ module Leftovers
98
94
  node = node.first
99
95
  case node.type
100
96
  # just collects the :call=, super will collect the :call
101
- when :send, :csend then add_call(:"#{node.name}=")
97
+ when :send, :csend then calls << :"#{node.name}="
102
98
  # just collects the call, super will collect the definition
103
- when :ivasgn, :gvasgn, :cvasgn then add_call(node.name)
99
+ when :ivasgn, :gvasgn, :cvasgn then calls << node.name
104
100
  when :lvasgn then nil # we don't care about lvasgn
105
101
  # :nocov:
106
102
  else raise Leftovers::UnexpectedCase, "Unhandled value #{node.type.inspect}"
@@ -115,9 +111,7 @@ module Leftovers
115
111
  end
116
112
 
117
113
  def collect_dynamic(node)
118
- node.keep_line = @allow_lines.include?(node.loc.line)
119
-
120
- Leftovers.config.dynamic.process(node, self)
114
+ Leftovers.config.dynamic.process(nil, node, node, self)
121
115
  rescue StandardError => e
122
116
  raise ::Leftovers::Error, "#{e.class}: #{e.message}\n" \
123
117
  "when processing #{node} at #{filename}:#{node.loc.line}:#{node.loc.column}", e.backtrace
@@ -126,7 +120,7 @@ module Leftovers
126
120
  private
127
121
 
128
122
  def build_send_wrapper_for(node, name)
129
- ::Leftovers::AST::Node.new(
123
+ ::Leftovers::AST::SendNode.new(
130
124
  :send, [nil, name.to_sym, *node.arguments], location: node.location
131
125
  )
132
126
  end
@@ -4,11 +4,12 @@ require 'fast_ignore'
4
4
 
5
5
  module Leftovers
6
6
  class FileList < ::FastIgnore
7
- def initialize
7
+ def initialize(**arguments)
8
8
  super(
9
9
  ignore_rules: Leftovers.config.exclude_paths,
10
10
  include_rules: Leftovers.config.include_paths,
11
- root: Leftovers.pwd
11
+ root: Leftovers.pwd,
12
+ **arguments
12
13
  )
13
14
  end
14
15
 
@@ -3,15 +3,32 @@
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module And
6
- def self.build(matchers)
7
- matchers = matchers.compact
8
- case matchers.length
9
- # :nocov:
10
- when 0 then nil
11
- # :nocov:
12
- when 1 then matchers.first
13
- when 2 then ::Leftovers::Matchers::And.new(matchers.first, matchers[1])
14
- else ::Leftovers::Matchers::All.new(matchers.dup)
6
+ class << self
7
+ def build(matchers)
8
+ matchers = flatten(matchers).compact
9
+ case matchers.length
10
+ when 0 then nil
11
+ when 1 then matchers.first
12
+ when 2 then ::Leftovers::Matchers::And.new(matchers.first, matchers[1])
13
+ else ::Leftovers::Matchers::All.new(matchers.dup)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def flatten(value)
20
+ case value
21
+ when ::Leftovers::Matchers::And
22
+ [*flatten(value.lhs), *flatten(value.rhs)]
23
+ # :nocov: # not sure how to make this happen
24
+ when ::Leftovers::Matchers::All
25
+ flatten(value.matchers)
26
+ # :nocov:
27
+ when Array
28
+ value.flat_map { |v| flatten(v) }
29
+ else
30
+ [value]
31
+ end
15
32
  end
16
33
  end
17
34
  end
@@ -16,6 +16,28 @@ module Leftovers
16
16
  end
17
17
  end
18
18
 
19
+ def build_from_hash( # rubocop:disable Metrics/ParameterLists
20
+ names: nil, match: nil, has_prefix: nil, has_suffix: nil,
21
+ document: false,
22
+ paths: nil,
23
+ has_arguments: nil,
24
+ has_receiver: nil,
25
+ type: nil,
26
+ privacy: nil,
27
+ unless_arg: nil, all: nil, any: nil
28
+ )
29
+ ::Leftovers::MatcherBuilders::And.build([
30
+ build_node_name_matcher(names, match, has_prefix, has_suffix),
31
+ ::Leftovers::MatcherBuilders::Document.build(document),
32
+ ::Leftovers::MatcherBuilders::NodePath.build(paths),
33
+ ::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
34
+ ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
35
+ ::Leftovers::MatcherBuilders::NodePrivacy.build(privacy),
36
+ ::Leftovers::MatcherBuilders::NodeType.build(type),
37
+ build_unless_matcher(unless_arg), build_all_matcher(all), build_any_matcher(any)
38
+ ])
39
+ end
40
+
19
41
  private
20
42
 
21
43
  def build_node_name_matcher(names, match, has_prefix, has_suffix)
@@ -35,26 +57,16 @@ module Leftovers
35
57
  )
36
58
  end
37
59
 
38
- def build_from_hash( # rubocop:disable Metrics/ParameterLists
39
- names: nil, match: nil, has_prefix: nil, has_suffix: nil,
40
- document: false,
41
- paths: nil,
42
- has_arguments: nil,
43
- has_receiver: nil,
44
- type: nil,
45
- privacy: nil,
46
- unless_arg: nil
47
- )
48
- ::Leftovers::MatcherBuilders::And.build([
49
- build_node_name_matcher(names, match, has_prefix, has_suffix),
50
- ::Leftovers::MatcherBuilders::Document.build(document),
51
- ::Leftovers::MatcherBuilders::NodePath.build(paths),
52
- ::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
53
- ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
54
- ::Leftovers::MatcherBuilders::NodePrivacy.build(privacy),
55
- ::Leftovers::MatcherBuilders::NodeType.build(type),
56
- build_unless_matcher(unless_arg)
57
- ])
60
+ def build_all_matcher(all)
61
+ return unless all
62
+
63
+ ::Leftovers::MatcherBuilders::And.build(
64
+ all.map { |pattern| ::Leftovers::MatcherBuilders::Node.build(pattern) }
65
+ )
66
+ end
67
+
68
+ def build_any_matcher(any)
69
+ ::Leftovers::MatcherBuilders::Node.build(any)
58
70
  end
59
71
  end
60
72
  end
@@ -20,7 +20,9 @@ module Leftovers
20
20
  if ::Leftovers.each_or_self(keywords).include?('**')
21
21
  ::Leftovers::Matchers::NodeType.new(:pair)
22
22
  else
23
- ::Leftovers::MatcherBuilders::NodePairName.build(keywords)
23
+ ::Leftovers::MatcherBuilders::NodePairKey.build(
24
+ ::Leftovers::MatcherBuilders::Node.build(keywords)
25
+ )
24
26
  end
25
27
  end
26
28
  end