leftovers 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -3
  3. data/docs/Configuration.md +82 -18
  4. data/leftovers.gemspec +1 -1
  5. data/lib/config/actionmailer.yml +11 -11
  6. data/lib/config/activesupport.yml +1 -1
  7. data/lib/config/rails.yml +1 -1
  8. data/lib/config/railties.yml +11 -0
  9. data/lib/config/ruby.yml +72 -0
  10. data/lib/leftovers/ast/node.rb +16 -11
  11. data/lib/leftovers/config.rb +1 -24
  12. data/lib/leftovers/config_loader/argument_position_schema.rb +11 -0
  13. data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
  14. data/lib/leftovers/config_loader/attribute.rb +30 -0
  15. data/lib/leftovers/config_loader/document_schema.rb +21 -0
  16. data/lib/leftovers/config_loader/dynamic_schema.rb +17 -0
  17. data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
  18. data/lib/leftovers/config_loader/has_value_schema.rb +18 -0
  19. data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
  20. data/lib/leftovers/config_loader/node.rb +106 -0
  21. data/lib/leftovers/config_loader/object_schema.rb +189 -0
  22. data/lib/leftovers/config_loader/privacy_processor_schema.rb +12 -0
  23. data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
  24. data/lib/leftovers/config_loader/require_schema.rb +11 -0
  25. data/lib/leftovers/config_loader/rule_pattern_schema.rb +18 -0
  26. data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
  27. data/lib/leftovers/config_loader/scalar_value_schema.rb +14 -0
  28. data/lib/leftovers/config_loader/schema.rb +21 -0
  29. data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
  30. data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
  31. data/lib/leftovers/config_loader/string_schema.rb +14 -0
  32. data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
  33. data/lib/leftovers/config_loader/suggester.rb +22 -0
  34. data/lib/leftovers/config_loader/transform_schema.rb +28 -0
  35. data/lib/leftovers/config_loader/true_schema.rb +18 -0
  36. data/lib/leftovers/config_loader/value_matcher_schema.rb +18 -0
  37. data/lib/leftovers/config_loader/value_or_array_schema.rb +64 -0
  38. data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
  39. data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
  40. data/lib/leftovers/config_loader.rb +82 -0
  41. data/lib/leftovers/definition_node.rb +6 -17
  42. data/lib/leftovers/definition_node_set.rb +11 -0
  43. data/lib/leftovers/definition_to_add.rb +31 -0
  44. data/lib/leftovers/dynamic_processors/call.rb +4 -3
  45. data/lib/leftovers/dynamic_processors/call_definition.rb +14 -7
  46. data/lib/leftovers/dynamic_processors/definition.rb +8 -3
  47. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +18 -0
  48. data/lib/leftovers/dynamic_processors/set_privacy.rb +23 -0
  49. data/lib/leftovers/dynamic_processors.rb +2 -0
  50. data/lib/leftovers/file.rb +5 -1
  51. data/lib/leftovers/file_collector.rb +44 -17
  52. data/lib/leftovers/matcher_builders/node.rb +4 -0
  53. data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
  54. data/lib/leftovers/matcher_builders/node_type.rb +4 -4
  55. data/lib/leftovers/matcher_builders/node_value.rb +1 -1
  56. data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
  57. data/lib/leftovers/matcher_builders.rb +1 -0
  58. data/lib/leftovers/matchers/node_privacy.rb +19 -0
  59. data/lib/leftovers/matchers.rb +1 -0
  60. data/lib/leftovers/merged_config.rb +18 -34
  61. data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
  62. data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
  63. data/lib/leftovers/processor_builders/dynamic.rb +50 -16
  64. data/lib/leftovers/processor_builders/transform.rb +2 -2
  65. data/lib/leftovers/processor_builders/transform_set.rb +8 -8
  66. data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
  67. data/lib/leftovers/value_processors/each_positional_argument.rb +1 -1
  68. data/lib/leftovers/value_processors/return_definition_node.rb +14 -0
  69. data/lib/leftovers/value_processors/{return_string.rb → return_sym.rb} +1 -1
  70. data/lib/leftovers/value_processors.rb +2 -2
  71. data/lib/leftovers/version.rb +1 -1
  72. data/lib/leftovers.rb +23 -14
  73. metadata +54 -22
  74. data/lib/config/actioncable.yml +0 -4
  75. data/lib/leftovers/config_validator/error_processor.rb +0 -196
  76. data/lib/leftovers/config_validator/schema_hash.rb +0 -551
  77. data/lib/leftovers/config_validator.rb +0 -61
  78. data/lib/leftovers/value_processors/return_definition.rb +0 -22
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ValueTypeSchema < StringEnumSchema
6
+ value :String
7
+ value :Symbol
8
+ value :Integer
9
+ value :Float
10
+ value :Array
11
+ value :Hash
12
+ value :Proc
13
+ value :Method
14
+ value :Constant
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,82 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'yaml'
4
+ require 'leftovers'
5
+
6
+ module Leftovers
7
+ class ConfigLoader
8
+ autoload(:ArgumentPositionSchema, "#{__dir__}/config_loader/argument_position_schema")
9
+ autoload(:ArgumentlessTransformSchema, "#{__dir__}/config_loader/argumentless_transform_schema")
10
+ autoload(:Attribute, "#{__dir__}/config_loader/attribute")
11
+ autoload(:DocumentSchema, "#{__dir__}/config_loader/document_schema")
12
+ autoload(:DynamicSchema, "#{__dir__}/config_loader/dynamic_schema")
13
+ autoload(:HasArgumentSchema, "#{__dir__}/config_loader/has_argument_schema")
14
+ autoload(:HasValueSchema, "#{__dir__}/config_loader/has_value_schema")
15
+ autoload(:KeepTestOnlySchema, "#{__dir__}/config_loader/keep_test_only_schema")
16
+ autoload(:Node, "#{__dir__}/config_loader/node")
17
+ autoload(:ObjectSchema, "#{__dir__}/config_loader/object_schema")
18
+ autoload(:PrivacyProcessorSchema, "#{__dir__}/config_loader/privacy_processor_schema")
19
+ autoload(:PrivacySchema, "#{__dir__}/config_loader/privacy_schema")
20
+ autoload(:RequireSchema, "#{__dir__}/config_loader/require_schema")
21
+ autoload(:RulePatternSchema, "#{__dir__}/config_loader/rule_pattern_schema")
22
+ autoload(:ScalarArgumentSchema, "#{__dir__}/config_loader/scalar_argument_schema")
23
+ autoload(:ScalarValueSchema, "#{__dir__}/config_loader/scalar_value_schema")
24
+ autoload(:Schema, "#{__dir__}/config_loader/schema")
25
+ autoload(:Suggester, "#{__dir__}/config_loader/suggester")
26
+ autoload(:StringEnumSchema, "#{__dir__}/config_loader/string_enum_schema")
27
+ autoload(:StringPatternSchema, "#{__dir__}/config_loader/string_pattern_schema")
28
+ autoload(:StringSchema, "#{__dir__}/config_loader/string_schema")
29
+ autoload(:StringValueProcessorSchema, "#{__dir__}/config_loader/string_value_processor_schema")
30
+ autoload(:TransformSchema, "#{__dir__}/config_loader/transform_schema")
31
+ autoload(:TrueSchema, "#{__dir__}/config_loader/true_schema")
32
+ autoload(:ValueMatcherSchema, "#{__dir__}/config_loader/value_matcher_schema")
33
+ autoload(:ValueOrArraySchema, "#{__dir__}/config_loader/value_or_array_schema")
34
+ autoload(:ValueProcessorSchema, "#{__dir__}/config_loader/value_processor_schema")
35
+ autoload(:ValueTypeSchema, "#{__dir__}/config_loader/value_type_schema")
36
+
37
+ def self.load(name, path: nil, content: nil)
38
+ new(name, path: path, content: content).load
39
+ end
40
+
41
+ attr_reader :name
42
+
43
+ def initialize(name, path: nil, content: nil)
44
+ @name = name
45
+ @path = path
46
+ @content = content
47
+ end
48
+
49
+ def load
50
+ document = ::Leftovers::ConfigLoader::Node.new(parse, file)
51
+ DocumentSchema.validate(document)
52
+
53
+ all_errors = document.all_errors
54
+ return DocumentSchema.to_ruby(document) if all_errors.empty?
55
+
56
+ Leftovers.error(all_errors.join("\n"))
57
+ end
58
+
59
+ private
60
+
61
+ def path
62
+ @path ||= ::File.expand_path("../config/#{name}.yml", __dir__)
63
+ end
64
+
65
+ def file
66
+ @file ||= ::Leftovers::File.new(path)
67
+ end
68
+
69
+ def content
70
+ @content ||= file.exist? ? file.read : ''
71
+ end
72
+
73
+ def parse
74
+ parsed = Psych.parse(content)
75
+ parsed ||= Psych.parse('{}')
76
+ parsed.children.first
77
+ rescue ::Psych::SyntaxError => e
78
+ message = [e.problem, e.context].compact.join(' ')
79
+ Leftovers.error "Config SyntaxError: #{file.relative_path}:#{e.line}:#{e.column} #{message}"
80
+ end
81
+ end
82
+ end
@@ -1,19 +1,15 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- # To give to matchers before creating a Definition
4
-
5
3
  module Leftovers
6
4
  class DefinitionNode
7
- attr_reader :path, :name
5
+ attr_reader :name, :loc, :node
8
6
 
9
- def initialize(name, path)
7
+ def initialize(node, name:, location: node.loc.expression)
8
+ @node = node
10
9
  @name = name
11
- @path = path
12
-
13
- freeze
10
+ @loc = location
14
11
  end
15
12
 
16
- # these are the methods checked by things in lib/leftovers/matchers
17
13
  def kwargs
18
14
  nil
19
15
  end
@@ -22,15 +18,8 @@ module Leftovers
22
18
  nil
23
19
  end
24
20
 
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
21
+ def path
22
+ node.path
33
23
  end
34
- # :nocov:
35
24
  end
36
25
  end
@@ -0,0 +1,11 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ class DefinitionNodeSet
5
+ attr_reader :definitions
6
+
7
+ def initialize(definitions)
8
+ @definitions = definitions
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ class DefinitionToAdd
5
+ attr_reader :node, :name, :location
6
+
7
+ def initialize(node, name: node.name, location: node.loc.name)
8
+ @node = node
9
+ @name = name
10
+ @location = location
11
+ end
12
+
13
+ def privacy=(value)
14
+ @node.privacy = value
15
+ end
16
+
17
+ def keep?(file_collector)
18
+ @keep ||= file_collector.keep_line?(location.line) || ::Leftovers.config.keep === node
19
+ end
20
+
21
+ def test?(file_collector)
22
+ file_collector.test_line?(location.line) || ::Leftovers.config.test_only === node
23
+ end
24
+
25
+ def to_definition(file_collector)
26
+ return if keep?(file_collector)
27
+
28
+ Leftovers::Definition.new(name, location: location, test: test?(file_collector))
29
+ end
30
+ end
31
+ end
@@ -11,10 +11,11 @@ module Leftovers
11
11
  def process(node, file)
12
12
  return unless @matcher === node
13
13
 
14
- call = @processor.process(nil, node, node)
15
- return unless call
14
+ calls = @processor.process(nil, node, node)
16
15
 
17
- file.calls << call
16
+ ::Leftovers.each_or_self(calls) do |call|
17
+ file.calls << call
18
+ end
18
19
  end
19
20
  end
20
21
  end
@@ -9,18 +9,25 @@ module Leftovers
9
9
  @definition_processor = definition_processor
10
10
  end
11
11
 
12
- def process(node, file)
12
+ def process(node, file) # rubocop:disable Metrics/MethodLength
13
13
  return unless @matcher === node
14
14
 
15
- call = @call_processor.process(nil, node, node)
16
- (file.calls << call) if call
15
+ calls = @call_processor.process(nil, node, node)
17
16
 
18
- return if node.keep_line?
17
+ ::Leftovers.each_or_self(calls) do |call|
18
+ file.calls << call
19
+ end
19
20
 
20
- definition = @definition_processor.process(nil, node, node)
21
- return unless definition
21
+ return if node.keep_line?
22
22
 
23
- file.definitions << definition
23
+ definitions = @definition_processor.process(nil, node, node)
24
+ ::Leftovers.each_or_self(definitions) do |definition|
25
+ if definition.is_a?(DefinitionNodeSet)
26
+ file.add_definition_set(definition)
27
+ else
28
+ file.add_definition(definition, loc: definition.loc)
29
+ end
30
+ end
24
31
  end
25
32
  end
26
33
  end
@@ -12,10 +12,15 @@ module Leftovers
12
12
  return if node.keep_line?
13
13
  return unless @matcher === node
14
14
 
15
- definition = @processor.process(nil, node, node)
16
- return unless definition
15
+ definitions = @processor.process(nil, node, node)
17
16
 
18
- file.definitions << definition
17
+ ::Leftovers.each_or_self(definitions) do |definition|
18
+ if definition.is_a?(DefinitionNodeSet)
19
+ file.add_definition_set(definition)
20
+ else
21
+ file.add_definition(definition, loc: definition.loc)
22
+ end
23
+ end
19
24
  end
20
25
  end
21
26
  end
@@ -0,0 +1,18 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module DynamicProcessors
5
+ class SetDefaultPrivacy
6
+ def initialize(matcher, to)
7
+ @matcher = matcher
8
+ @to = to
9
+ end
10
+
11
+ def process(node, file)
12
+ return unless @matcher === node
13
+
14
+ file.default_method_privacy = @to
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module DynamicProcessors
5
+ class SetPrivacy
6
+ def initialize(matcher, processor, to)
7
+ @matcher = matcher
8
+ @processor = processor
9
+ @to = to
10
+ end
11
+
12
+ def process(node, file)
13
+ return unless @matcher === node
14
+
15
+ set_privacy = @processor.process(nil, node, node)
16
+
17
+ ::Leftovers.each_or_self(set_privacy) do |name|
18
+ file.set_privacy(name, @to)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -7,5 +7,7 @@ module Leftovers
7
7
  autoload(:Definition, "#{__dir__}/dynamic_processors/definition")
8
8
  autoload(:Each, "#{__dir__}/dynamic_processors/each")
9
9
  autoload(:Null, "#{__dir__}/dynamic_processors/null")
10
+ autoload(:SetDefaultPrivacy, "#{__dir__}/dynamic_processors/set_default_privacy")
11
+ autoload(:SetPrivacy, "#{__dir__}/dynamic_processors/set_privacy")
10
12
  end
11
13
  end
@@ -5,7 +5,11 @@ require 'pathname'
5
5
  module Leftovers
6
6
  class File < Pathname
7
7
  def relative_path
8
- @relative_path ||= relative_path_from(Leftovers.pwd)
8
+ @relative_path ||= begin
9
+ relative_path_from(Leftovers.pwd)
10
+ rescue ArgumentError
11
+ self
12
+ end
9
13
  end
10
14
 
11
15
  def test?
@@ -5,16 +5,19 @@ require 'parser'
5
5
 
6
6
  module Leftovers
7
7
  class FileCollector < ::Parser::AST::Processor # rubocop:disable Metrics/ClassLength
8
- attr_reader :calls, :definitions
8
+ attr_reader :calls
9
+ attr_accessor :default_method_privacy
9
10
 
10
11
  def initialize(ruby, file) # rubocop:disable Lint/MissingSuper
11
12
  @calls = []
12
- @definitions = []
13
+ @definitions_to_add = {}
13
14
  @allow_lines = Set.new.compare_by_identity
14
15
  @test_lines = Set.new.compare_by_identity
15
16
  @dynamic_lines = {}
16
17
  @ruby = ruby
17
18
  @file = file
19
+ @default_method_privacy = :public
20
+ @definition_sets_to_add = []
18
21
  end
19
22
 
20
23
  def filename
@@ -38,7 +41,6 @@ module Leftovers
38
41
  definitions.flatten!
39
42
  definitions.compact!
40
43
  definitions.uniq!
41
- definitions.reject! { |v| v == :keep }
42
44
  end
43
45
 
44
46
  def collect
@@ -76,6 +78,12 @@ module Leftovers
76
78
 
77
79
  # grab method definitions
78
80
  def on_def(node)
81
+ node.privacy = default_method_privacy
82
+ add_definition(node)
83
+ super
84
+ end
85
+
86
+ def on_defs(node)
79
87
  add_definition(node)
80
88
  super
81
89
  end
@@ -184,24 +192,41 @@ module Leftovers
184
192
  add_call(original_method.children.first)
185
193
  end
186
194
 
187
- private
195
+ def add_definition(node, name: node.name, loc: node.loc.name)
196
+ @definitions_to_add[name] =
197
+ ::Leftovers::DefinitionToAdd.new(node, name: name, location: loc)
198
+ end
188
199
 
189
- def test_line?(loc)
190
- @file.test? ||
191
- @test_lines.include?(loc.line)
200
+ def add_definition_set(definition_node_set)
201
+ @definition_sets_to_add << definition_node_set.definitions.map do |definition_node|
202
+ ::Leftovers::DefinitionToAdd.new(definition_node, location: definition_node.loc)
203
+ end
192
204
  end
193
205
 
194
- def test_node?(node, loc)
195
- test_line?(loc) || ::Leftovers.config.test_only === node
206
+ def set_privacy(name, to)
207
+ @definitions_to_add[name]&.privacy = to
196
208
  end
197
209
 
198
- def add_definition(node, name: node.name, loc: node.loc.name)
199
- return if @allow_lines.include?(loc.line)
200
- return if Leftovers.config.keep === node
210
+ def definitions
211
+ @definitions ||= @definitions_to_add.each_value.map { |d| d.to_definition(self) }.compact +
212
+ @definition_sets_to_add.map do |definition_set|
213
+ next nil if definition_set.any? { |d| d.keep?(self) }
201
214
 
202
- definitions << Leftovers::Definition.new(name, location: loc, test: test_node?(node, loc))
215
+ ::Leftovers::DefinitionSet.new(definition_set.map { |d| d.to_definition(self) })
216
+ end.compact
203
217
  end
204
218
 
219
+ def test_line?(line)
220
+ @file.test? ||
221
+ @test_lines.include?(line)
222
+ end
223
+
224
+ def keep_line?(line)
225
+ @allow_lines.include?(line)
226
+ end
227
+
228
+ private
229
+
205
230
  def add_call(name)
206
231
  calls << name
207
232
  end
@@ -232,11 +257,14 @@ module Leftovers
232
257
 
233
258
  def collect_op_asgn(node)
234
259
  node = node.children.first
235
- # :nocov: # don't need else, it's exhaustive for callers
236
260
  case node.type
237
- # :nocov:
238
261
  when :send then collect_send_op_asgn(node)
239
262
  when :ivasgn, :gvasgn, :cvasgn then collect_var_op_asgn(node)
263
+ when :lvasgn then nil # we don't care about lvasgn
264
+ # :nocov:
265
+ else
266
+ raise "Unrecognized op_asgn node type #{node.type}"
267
+ # :nocov:
240
268
  end
241
269
  end
242
270
 
@@ -256,9 +284,8 @@ module Leftovers
256
284
  )
257
285
  end
258
286
 
259
- def collect_dynamic(node) # rubocop:disable Metrics/AbcSize
287
+ def collect_dynamic(node)
260
288
  node.keep_line = @allow_lines.include?(node.loc.line)
261
- node.test_line = test_line?(node.loc) unless node.keep_line?
262
289
 
263
290
  Leftovers.config.dynamic.process(node, self)
264
291
  rescue StandardError => e
@@ -23,6 +23,8 @@ module Leftovers
23
23
  paths: nil,
24
24
  has_arguments: nil,
25
25
  has_receiver: nil,
26
+ type: nil,
27
+ privacy: nil,
26
28
  unless_arg: nil
27
29
  )
28
30
  ::Leftovers::MatcherBuilders::And.build([
@@ -34,6 +36,8 @@ module Leftovers
34
36
  ::Leftovers::MatcherBuilders::NodePath.build(paths),
35
37
  ::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
36
38
  ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
39
+ ::Leftovers::MatcherBuilders::NodePrivacy.build(privacy),
40
+ ::Leftovers::MatcherBuilders::NodeType.build(type),
37
41
  ::Leftovers::MatcherBuilders::Unless.build(
38
42
  (::Leftovers::MatcherBuilders::Node.build(unless_arg) if unless_arg)
39
43
  )
@@ -0,0 +1,13 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module MatcherBuilders
5
+ module NodePrivacy
6
+ def self.build(privacy_settings)
7
+ ::Leftovers::MatcherBuilders::Or.each_or_self(privacy_settings) do |privacy|
8
+ ::Leftovers::Matchers::NodePrivacy.new(privacy)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -14,12 +14,12 @@ module Leftovers
14
14
  when 'Float' then ::Leftovers::Matchers::NodeType.new(:float)
15
15
  when 'Array' then ::Leftovers::Matchers::NodeType.new(:array)
16
16
  when 'Hash' then ::Leftovers::Matchers::NodeType.new(:hash)
17
-
18
17
  when 'Proc' then ::Leftovers::Matchers::Predicate.new(:proc?)
19
- # when 'Method' then ::Leftovers::Matchers::NodeType.new(Set[:send, :csend, :def])
20
- # when 'Constant' then ::Leftovers::Matchers::NodeType.new(Set[:const, :class, :module])
18
+ when 'Method' then ::Leftovers::Matchers::NodeType.new(Set[:send, :csend, :def, :defs])
19
+ when 'Constant'
20
+ ::Leftovers::Matchers::NodeType.new(Set[:const, :class, :module, :casgn])
21
21
  # :nocov:
22
- else raise
22
+ else raise "Unknown type #{type}"
23
23
  # :nocov:
24
24
  end
25
25
  end
@@ -7,7 +7,7 @@ module Leftovers
7
7
  def build(pattern) # rubocop:disable Metrics/MethodLength
8
8
  ::Leftovers::MatcherBuilders::Or.each_or_self(pattern) do |pat|
9
9
  case pat
10
- when ::Integer, true, false, nil
10
+ when ::Integer, ::Float, true, false, nil
11
11
  ::Leftovers::Matchers::NodeScalarValue.new(pat)
12
12
  when ::String
13
13
  ::Leftovers::MatcherBuilders::NodeName.build(pat)
@@ -3,15 +3,24 @@
3
3
  module Leftovers
4
4
  module MatcherBuilders
5
5
  module StringPattern
6
- def self.build(match: nil, has_prefix: nil, has_suffix: nil)
7
- if match
6
+ def self.build(match: nil, has_prefix: nil, has_suffix: nil) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
7
+ has_prefix = ::Regexp.escape(has_prefix) if has_prefix
8
+ has_suffix = ::Regexp.escape(has_suffix) if has_suffix
9
+
10
+ if match && has_prefix && has_suffix
11
+ /\A(?=#{match}\z)(?=#{has_prefix}).*#{has_suffix}\z/
12
+ elsif match && has_prefix
13
+ /\A(?=#{match}\z)#{has_prefix}/
14
+ elsif match && has_suffix
15
+ /\A(?=#{match}\z).*#{has_suffix}\z/
16
+ elsif match
8
17
  /\A#{match}\z/
9
18
  elsif has_prefix && has_suffix
10
- /\A#{::Regexp.escape(has_prefix)}.*#{::Regexp.escape(has_suffix)}\z/
19
+ /\A(?=#{has_prefix}).*#{has_suffix}\z/
11
20
  elsif has_prefix
12
- /\A#{::Regexp.escape(has_prefix)}/
21
+ /\A#{has_prefix}/
13
22
  elsif has_suffix
14
- /#{::Regexp.escape(has_suffix)}\z/
23
+ /#{has_suffix}\z/
15
24
  end
16
25
  end
17
26
  end
@@ -15,6 +15,7 @@ module Leftovers
15
15
  autoload(:NodePairName, "#{__dir__}/matcher_builders/node_pair_name")
16
16
  autoload(:NodePairValue, "#{__dir__}/matcher_builders/node_pair_value")
17
17
  autoload(:NodePath, "#{__dir__}/matcher_builders/node_path")
18
+ autoload(:NodePrivacy, "#{__dir__}/matcher_builders/node_privacy")
18
19
  autoload(:NodeType, "#{__dir__}/matcher_builders/node_type")
19
20
  autoload(:NodeValue, "#{__dir__}/matcher_builders/node_value")
20
21
  autoload(:Or, "#{__dir__}/matcher_builders/or")
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module Matchers
5
+ class NodePrivacy
6
+ def initialize(privacy_matcher)
7
+ @privacy_matcher = privacy_matcher
8
+
9
+ freeze
10
+ end
11
+
12
+ def ===(node)
13
+ @privacy_matcher === node.privacy
14
+ end
15
+
16
+ freeze
17
+ end
18
+ end
19
+ end
@@ -19,6 +19,7 @@ module Leftovers
19
19
  autoload(:NodeName, "#{__dir__}/matchers/node_name")
20
20
  autoload(:NodePairValue, "#{__dir__}/matchers/node_pair_value")
21
21
  autoload(:NodePath, "#{__dir__}/matchers/node_path")
22
+ autoload(:NodePrivacy, "#{__dir__}/matchers/node_privacy")
22
23
  autoload(:NodeScalarValue, "#{__dir__}/matchers/node_scalar_value")
23
24
  autoload(:NodeType, "#{__dir__}/matchers/node_type")
24
25
  autoload(:Not, "#{__dir__}/matchers/not")
@@ -4,7 +4,7 @@ require 'set'
4
4
  require 'fast_ignore'
5
5
 
6
6
  module Leftovers
7
- class MergedConfig # rubocop:disable Metrics/ClassLength
7
+ class MergedConfig
8
8
  def initialize(load_defaults: false)
9
9
  @configs = []
10
10
  @loaded_configs = Set.new
@@ -24,9 +24,7 @@ module Leftovers
24
24
  @configs << config
25
25
  @loaded_configs << config.name
26
26
  config.gems.each { |gem| self << gem }
27
- config.requires.each do |req|
28
- Leftovers.try_require(req, message: "cannot require '#{req}' from #{config.name}.yml")
29
- end
27
+ require_requires(config)
30
28
  end
31
29
 
32
30
  def project_config
@@ -66,51 +64,27 @@ module Leftovers
66
64
  end
67
65
 
68
66
  def test_paths
69
- @test_paths ||= FastIgnore.new(
70
- include_rules: @configs.flat_map(&:test_paths),
71
- gitignore: false,
72
- root: Leftovers.pwd
73
- )
67
+ @test_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:test_paths))
74
68
  end
75
69
 
76
70
  def haml_paths
77
- @haml_paths ||= FastIgnore.new(
78
- include_rules: @configs.flat_map(&:haml_paths),
79
- gitignore: false,
80
- root: Leftovers.pwd
81
- )
71
+ @haml_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:haml_paths))
82
72
  end
83
73
 
84
74
  def slim_paths
85
- @slim_paths ||= FastIgnore.new(
86
- include_rules: @configs.flat_map(&:slim_paths),
87
- gitignore: false,
88
- root: Leftovers.pwd
89
- )
75
+ @slim_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:slim_paths))
90
76
  end
91
77
 
92
78
  def yaml_paths
93
- @yaml_paths ||= FastIgnore.new(
94
- include_rules: @configs.flat_map(&:yaml_paths),
95
- gitignore: false,
96
- root: Leftovers.pwd
97
- )
79
+ @yaml_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:yaml_paths))
98
80
  end
99
81
 
100
82
  def json_paths
101
- @json_paths ||= FastIgnore.new(
102
- include_rules: @configs.flat_map(&:json_paths),
103
- gitignore: false,
104
- root: Leftovers.pwd
105
- )
83
+ @json_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:json_paths))
106
84
  end
107
85
 
108
86
  def erb_paths
109
- @erb_paths ||= FastIgnore.new(
110
- include_rules: @configs.flat_map(&:erb_paths),
111
- gitignore: false,
112
- root: Leftovers.pwd
113
- )
87
+ @erb_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:erb_paths))
114
88
  end
115
89
 
116
90
  def dynamic
@@ -127,6 +101,16 @@ module Leftovers
127
101
 
128
102
  private
129
103
 
104
+ def require_requires(config)
105
+ config.requires.each do |req|
106
+ if req.is_a?(Hash) && req[:quiet]
107
+ Leftovers.try_require(req[:quiet])
108
+ else
109
+ Leftovers.try_require(req, message: "cannot require '#{req}' from #{config.name}.yml")
110
+ end
111
+ end
112
+ end
113
+
130
114
  def load_bundled_gem_config
131
115
  return unless Leftovers.try_require('bundler')
132
116