leftovers 0.5.5 → 0.8.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 +40 -2
  3. data/README.md +22 -1
  4. data/docs/Configuration.md +173 -42
  5. data/docs/Custom-Precompilers.md +38 -0
  6. data/leftovers.gemspec +8 -5
  7. data/lib/config/actionmailer.yml +11 -11
  8. data/lib/config/actionpack.yml +5 -3
  9. data/lib/config/activesupport.yml +1 -1
  10. data/lib/config/haml.yml +4 -2
  11. data/lib/config/rails.yml +1 -1
  12. data/lib/config/railties.yml +11 -0
  13. data/lib/config/ruby.yml +76 -8
  14. data/lib/config/slim.yml +4 -2
  15. data/lib/leftovers/ast/node.rb +16 -11
  16. data/lib/leftovers/cli.rb +5 -0
  17. data/lib/leftovers/collector.rb +5 -2
  18. data/lib/leftovers/config.rb +3 -38
  19. data/lib/leftovers/config_loader/argument_position_schema.rb +11 -0
  20. data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
  21. data/lib/leftovers/config_loader/attribute.rb +56 -0
  22. data/lib/leftovers/config_loader/built_in_precompiler_schema.rb +13 -0
  23. data/lib/leftovers/config_loader/document_schema.rb +48 -0
  24. data/lib/leftovers/config_loader/dynamic_schema.rb +17 -0
  25. data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
  26. data/lib/leftovers/config_loader/has_value_schema.rb +18 -0
  27. data/lib/leftovers/config_loader/inherit_schema_attributes.rb +22 -0
  28. data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
  29. data/lib/leftovers/config_loader/node.rb +106 -0
  30. data/lib/leftovers/config_loader/object_schema.rb +117 -0
  31. data/lib/leftovers/config_loader/precompile_schema.rb +12 -0
  32. data/lib/leftovers/config_loader/precompiler_schema.rb +11 -0
  33. data/lib/leftovers/config_loader/privacy_processor_schema.rb +10 -0
  34. data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
  35. data/lib/leftovers/config_loader/require_schema.rb +11 -0
  36. data/lib/leftovers/config_loader/rule_pattern_schema.rb +18 -0
  37. data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
  38. data/lib/leftovers/config_loader/scalar_value_schema.rb +14 -0
  39. data/lib/leftovers/config_loader/schema.rb +23 -0
  40. data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
  41. data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
  42. data/lib/leftovers/config_loader/string_schema.rb +14 -0
  43. data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
  44. data/lib/leftovers/config_loader/suggester.rb +22 -0
  45. data/lib/leftovers/config_loader/transform_schema.rb +26 -0
  46. data/lib/leftovers/config_loader/true_schema.rb +18 -0
  47. data/lib/leftovers/config_loader/value_matcher_schema.rb +18 -0
  48. data/lib/leftovers/config_loader/value_or_array_schema.rb +66 -0
  49. data/lib/leftovers/config_loader/value_or_object_schema.rb +40 -0
  50. data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
  51. data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
  52. data/lib/leftovers/config_loader.rb +86 -0
  53. data/lib/leftovers/definition.rb +1 -1
  54. data/lib/leftovers/definition_node.rb +6 -17
  55. data/lib/leftovers/definition_node_set.rb +11 -0
  56. data/lib/leftovers/definition_to_add.rb +31 -0
  57. data/lib/leftovers/dynamic_processors/call.rb +4 -7
  58. data/lib/leftovers/dynamic_processors/call_definition.rb +14 -11
  59. data/lib/leftovers/dynamic_processors/definition.rb +8 -7
  60. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +18 -0
  61. data/lib/leftovers/dynamic_processors/set_privacy.rb +23 -0
  62. data/lib/leftovers/dynamic_processors.rb +2 -0
  63. data/lib/leftovers/file.rb +12 -12
  64. data/lib/leftovers/file_collector/comments_processor.rb +57 -0
  65. data/lib/leftovers/file_collector/node_processor.rb +131 -0
  66. data/lib/leftovers/file_collector.rb +66 -169
  67. data/lib/leftovers/matcher_builders/and_not.rb +7 -5
  68. data/lib/leftovers/matcher_builders/document.rb +13 -0
  69. data/lib/leftovers/matcher_builders/name.rb +18 -17
  70. data/lib/leftovers/matcher_builders/node.rb +48 -28
  71. data/lib/leftovers/matcher_builders/node_has_argument.rb +48 -53
  72. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +13 -10
  73. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +29 -15
  74. data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
  75. data/lib/leftovers/matcher_builders/node_type.rb +4 -4
  76. data/lib/leftovers/matcher_builders/node_value.rb +28 -23
  77. data/lib/leftovers/matcher_builders/or.rb +50 -50
  78. data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
  79. data/lib/leftovers/matcher_builders.rb +2 -0
  80. data/lib/leftovers/matchers/all.rb +0 -4
  81. data/lib/leftovers/matchers/and.rb +0 -4
  82. data/lib/leftovers/matchers/any.rb +0 -4
  83. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +1 -7
  84. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +1 -7
  85. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +0 -4
  86. data/lib/leftovers/matchers/node_name.rb +0 -4
  87. data/lib/leftovers/matchers/node_pair_value.rb +0 -4
  88. data/lib/leftovers/matchers/node_path.rb +0 -4
  89. data/lib/leftovers/matchers/node_privacy.rb +19 -0
  90. data/lib/leftovers/matchers/node_scalar_value.rb +0 -4
  91. data/lib/leftovers/matchers/node_type.rb +0 -4
  92. data/lib/leftovers/matchers/not.rb +0 -4
  93. data/lib/leftovers/matchers/or.rb +0 -4
  94. data/lib/leftovers/matchers.rb +1 -0
  95. data/lib/leftovers/merged_config.rb +15 -33
  96. data/lib/leftovers/precompilers/erb.rb +22 -0
  97. data/lib/leftovers/precompilers/haml.rb +15 -0
  98. data/lib/leftovers/precompilers/json.rb +27 -0
  99. data/lib/leftovers/precompilers/precompiler.rb +28 -0
  100. data/lib/leftovers/precompilers/slim.rb +15 -0
  101. data/lib/leftovers/precompilers/yaml.rb +75 -0
  102. data/lib/leftovers/precompilers.rb +50 -0
  103. data/lib/leftovers/processor_builders/action.rb +48 -39
  104. data/lib/leftovers/processor_builders/add_prefix.rb +2 -2
  105. data/lib/leftovers/processor_builders/add_suffix.rb +2 -2
  106. data/lib/leftovers/processor_builders/argument.rb +8 -11
  107. data/lib/leftovers/processor_builders/dynamic.rb +51 -16
  108. data/lib/leftovers/processor_builders/each.rb +2 -2
  109. data/lib/leftovers/processor_builders/each_action.rb +33 -33
  110. data/lib/leftovers/processor_builders/each_dynamic.rb +4 -8
  111. data/lib/leftovers/processor_builders/each_for_definition_set.rb +25 -21
  112. data/lib/leftovers/processor_builders/keyword.rb +3 -4
  113. data/lib/leftovers/processor_builders/transform.rb +4 -4
  114. data/lib/leftovers/processor_builders/transform_chain.rb +16 -8
  115. data/lib/leftovers/processor_builders/transform_set.rb +32 -28
  116. data/lib/leftovers/rake_task.rb +1 -1
  117. data/lib/leftovers/todo_reporter.rb +10 -35
  118. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +3 -10
  119. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +3 -10
  120. data/lib/leftovers/value_processors/delete_prefix.rb +0 -6
  121. data/lib/leftovers/value_processors/delete_suffix.rb +0 -6
  122. data/lib/leftovers/value_processors/each.rb +1 -1
  123. data/lib/leftovers/value_processors/each_for_definition_set.rb +4 -10
  124. data/lib/leftovers/value_processors/each_keyword.rb +1 -1
  125. data/lib/leftovers/value_processors/each_keyword_argument.rb +1 -1
  126. data/lib/leftovers/value_processors/each_positional_argument.rb +3 -2
  127. data/lib/leftovers/value_processors/keyword.rb +3 -11
  128. data/lib/leftovers/value_processors/keyword_argument.rb +2 -10
  129. data/lib/leftovers/value_processors/return_definition_node.rb +14 -0
  130. data/lib/leftovers/value_processors/{return_string.rb → return_sym.rb} +1 -1
  131. data/lib/leftovers/value_processors/split.rb +2 -2
  132. data/lib/leftovers/value_processors.rb +2 -2
  133. data/lib/leftovers/version.rb +1 -1
  134. data/lib/leftovers.rb +66 -23
  135. metadata +98 -39
  136. data/lib/config/actioncable.yml +0 -4
  137. data/lib/leftovers/backports.rb +0 -40
  138. data/lib/leftovers/config_validator/error_processor.rb +0 -196
  139. data/lib/leftovers/config_validator/schema_hash.rb +0 -530
  140. data/lib/leftovers/config_validator.rb +0 -60
  141. data/lib/leftovers/erb.rb +0 -20
  142. data/lib/leftovers/haml.rb +0 -21
  143. data/lib/leftovers/slim.rb +0 -21
  144. data/lib/leftovers/value_processors/return_definition.rb +0 -26
@@ -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 Leftovers::UnexpectedCase, "Unhandled value #{type.inspect}"
23
23
  # :nocov:
24
24
  end
25
25
  end
@@ -4,17 +4,15 @@ module Leftovers
4
4
  module MatcherBuilders
5
5
  module NodeValue
6
6
  class << self
7
- def build(pattern) # rubocop:disable Metrics/MethodLength
8
- ::Leftovers::MatcherBuilders::Or.each_or_self(pattern) do |pat|
9
- case pat
10
- when ::Integer, true, false, nil
11
- ::Leftovers::Matchers::NodeScalarValue.new(pat)
12
- when ::String
13
- ::Leftovers::MatcherBuilders::NodeName.build(pat)
14
- when ::Hash
15
- build_from_hash(**pat)
7
+ def build(patterns)
8
+ ::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pattern|
9
+ case pattern
10
+ when ::Integer, ::Float, true, false, nil
11
+ ::Leftovers::Matchers::NodeScalarValue.new(pattern)
12
+ when ::String then ::Leftovers::MatcherBuilders::NodeName.build(pattern)
13
+ when ::Hash then build_from_hash(**pattern)
16
14
  # :nocov:
17
- else raise
15
+ else raise Leftovers::UnexpectedCase, "Unhandled value #{pattern.inspect}"
18
16
  # :nocov:
19
17
  end
20
18
  end
@@ -22,27 +20,34 @@ module Leftovers
22
20
 
23
21
  private
24
22
 
25
- def build_from_hash( # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
23
+ def build_node_name(match, has_prefix, has_suffix)
24
+ ::Leftovers::MatcherBuilders::NodeName.build(
25
+ match: match, has_prefix: has_prefix, has_suffix: has_suffix
26
+ )
27
+ end
28
+
29
+ def build_unless(unless_arg)
30
+ return unless unless_arg
31
+
32
+ ::Leftovers::MatcherBuilders::Unless.build(
33
+ ::Leftovers::MatcherBuilders::NodeValue.build(unless_arg)
34
+ )
35
+ end
36
+
37
+ def build_from_hash( # rubocop:disable Metrics/ParameterLists
26
38
  at: nil, has_value: nil,
27
39
  match: nil, has_prefix: nil, has_suffix: nil,
28
40
  type: nil,
29
41
  has_receiver: nil,
30
42
  unless_arg: nil
31
43
  )
32
- matcher = ::Leftovers::MatcherBuilders::And.build([
33
- ::Leftovers::MatcherBuilders::NodeHasArgument.build(
34
- at: at, has_value: has_value
35
- ),
36
- ::Leftovers::MatcherBuilders::NodeName.build(
37
- match: match, has_prefix: has_prefix, has_suffix: has_suffix
38
- ),
44
+ ::Leftovers::MatcherBuilders::And.build([
45
+ ::Leftovers::MatcherBuilders::NodeHasArgument.build(at: at, has_value: has_value),
46
+ build_node_name(match, has_prefix, has_suffix),
39
47
  ::Leftovers::MatcherBuilders::NodeType.build(type),
40
- ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver)
48
+ ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
49
+ build_unless(unless_arg)
41
50
  ])
42
-
43
- ::Leftovers::MatcherBuilders::AndNot.build(
44
- matcher, ::Leftovers::MatcherBuilders::NodeValue.build(unless_arg)
45
- )
46
51
  end
47
52
  end
48
53
  end
@@ -5,68 +5,68 @@ require 'set'
5
5
  module Leftovers
6
6
  module MatcherBuilders
7
7
  module Or
8
- def self.each_or_self(value, &block)
9
- case value
10
- when nil then nil
11
- when Array then build(value.map(&block))
12
- else build([yield(value)])
8
+ class << self
9
+ def each_or_self(value, &block)
10
+ case value
11
+ when nil then nil
12
+ when Array then build(value.map(&block))
13
+ else build([yield(value)])
14
+ end
13
15
  end
14
- end
15
16
 
16
- def self.build(matchers)
17
- matchers = compact(matchers)
18
- case matchers.length
19
- # :nocov:
20
- when 0 then nil
21
- # :nocov:
22
- when 1 then matchers.first
23
- when 2 then ::Leftovers::Matchers::Or.new(matchers.first, matchers[1])
24
- else ::Leftovers::Matchers::Any.new(matchers.dup)
17
+ def build(matchers)
18
+ matchers = compact(matchers)
19
+ case matchers.length
20
+ # :nocov:
21
+ when 0 then nil
22
+ # :nocov:
23
+ when 1 then matchers.first
24
+ when 2 then ::Leftovers::Matchers::Or.new(matchers.first, matchers[1])
25
+ else ::Leftovers::Matchers::Any.new(matchers.dup)
26
+ end
25
27
  end
26
- end
27
28
 
28
- def self.flatten(value) # rubocop:disable Metrics/MethodLength
29
- case value
30
- when ::Leftovers::Matchers::Or
31
- [*flatten(value.lhs), *flatten(value.rhs)]
32
- when ::Leftovers::Matchers::Any
33
- flatten(value.matchers)
34
- when Array
35
- ret = value.map { |v| flatten(v) }
36
- ret.flatten!(1)
37
- ret
38
- else
39
- value
29
+ private
30
+
31
+ def flatten(value)
32
+ case value
33
+ when ::Leftovers::Matchers::Or
34
+ [*flatten(value.lhs), *flatten(value.rhs)]
35
+ when ::Leftovers::Matchers::Any
36
+ flatten(value.matchers)
37
+ when Array
38
+ value.flat_map { |v| flatten(v) }
39
+ else
40
+ value
41
+ end
40
42
  end
41
- end
42
43
 
43
- def self.compact(matchers) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize,
44
- return matchers if matchers.length <= 1
44
+ def group_by_compactable(matchers)
45
+ groups = matchers.group_by do |matcher|
46
+ case matcher
47
+ when ::Integer, ::Symbol then :set
48
+ when ::Regexp then :regexp
49
+ else :uncompactable
50
+ end
51
+ end
45
52
 
46
- set = Set.new
47
- regexps = []
48
- uncompactable = []
53
+ groups.transform_values { |v| Leftovers.unwrap_array(v) }
54
+ end
49
55
 
50
- matchers = flatten(matchers)
56
+ def build_grouped(set: nil, regexp: nil, uncompactable: nil)
57
+ set = set.to_set if set.is_a?(Array)
58
+ regexp = Regexp.union(regexp) if regexp.is_a?(Array)
51
59
 
52
- matchers.each do |matcher|
53
- case matcher
54
- when nil then nil
55
- when ::Integer, ::Symbol then set << matcher
56
- # when ::Set then set.merge(matcher) # may not be necessary
57
- when ::Regexp then regexps << matcher
58
- else uncompactable << matcher
59
- end
60
+ [set, regexp].concat(Array(uncompactable)).compact
60
61
  end
61
62
 
62
- set = set.first if set.length <= 1
63
- regexps = if regexps.length <= 1
64
- regexps.first
65
- else
66
- Regexp.union(regexps)
67
- end
63
+ def compact(matchers)
64
+ matchers = flatten(matchers)
65
+
66
+ return matchers if matchers.length <= 1
68
67
 
69
- [set, regexps].compact.concat(uncompactable)
68
+ build_grouped(**group_by_compactable(matchers))
69
+ end
70
70
  end
71
71
  end
72
72
  end
@@ -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
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
@@ -4,6 +4,7 @@ module Leftovers
4
4
  module MatcherBuilders
5
5
  autoload(:AndNot, "#{__dir__}/matcher_builders/and_not")
6
6
  autoload(:And, "#{__dir__}/matcher_builders/and")
7
+ autoload(:Document, "#{__dir__}/matcher_builders/document")
7
8
  autoload(:Name, "#{__dir__}/matcher_builders/name")
8
9
  autoload(:Node, "#{__dir__}/matcher_builders/node")
9
10
  autoload(:NodeHasArgument, "#{__dir__}/matcher_builders/node_has_argument")
@@ -14,6 +15,7 @@ module Leftovers
14
15
  autoload(:NodePairName, "#{__dir__}/matcher_builders/node_pair_name")
15
16
  autoload(:NodePairValue, "#{__dir__}/matcher_builders/node_pair_value")
16
17
  autoload(:NodePath, "#{__dir__}/matcher_builders/node_path")
18
+ autoload(:NodePrivacy, "#{__dir__}/matcher_builders/node_privacy")
17
19
  autoload(:NodeType, "#{__dir__}/matcher_builders/node_type")
18
20
  autoload(:NodeValue, "#{__dir__}/matcher_builders/node_value")
19
21
  autoload(:Or, "#{__dir__}/matcher_builders/or")
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class All
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(matchers)
11
7
  @matchers = matchers
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class And
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(lhs, rhs)
11
7
  @lhs = lhs
12
8
  @rhs = rhs
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class Any
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  attr_reader :matchers
11
7
 
12
8
  def initialize(matchers)
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeHasAnyKeywordArgument
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(pair_matcher)
11
7
  @pair_matcher = pair_matcher
12
8
 
@@ -17,9 +13,7 @@ module Leftovers
17
13
  kwargs = node.kwargs
18
14
  return false unless kwargs
19
15
 
20
- kwargs.children.any? do |pair|
21
- @pair_matcher === pair
22
- end
16
+ kwargs.children.any?(@pair_matcher)
23
17
  end
24
18
 
25
19
  freeze
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeHasAnyPositionalArgumentWithValue
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(matcher)
11
7
  @matcher = matcher
12
8
 
@@ -17,9 +13,7 @@ module Leftovers
17
13
  args = node.positional_arguments
18
14
  return false unless args
19
15
 
20
- args.any? do |value|
21
- @matcher === value
22
- end
16
+ args.any?(@matcher)
23
17
  end
24
18
 
25
19
  freeze
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeHasPositionalArgumentWithValue
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(position, matcher)
11
7
  @position = position
12
8
  @matcher = matcher
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeName
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(name_matcher)
11
7
  @name_matcher = name_matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodePairValue
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(value_matcher)
11
7
  @value_matcher = value_matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodePath
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(path_matcher)
11
7
  @path_matcher = path_matcher
12
8
 
@@ -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
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeScalarValue
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(matcher)
11
7
  @matcher = matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class NodeType
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(type_matcher)
11
7
  @type_matcher = type_matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class Not
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  def initialize(matcher)
11
7
  @matcher = matcher
12
8
 
@@ -3,10 +3,6 @@
3
3
  module Leftovers
4
4
  module Matchers
5
5
  class Or
6
- # :nocov:
7
- using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
8
- # :nocov:
9
-
10
6
  attr_reader :lhs, :rhs
11
7
 
12
8
  def initialize(lhs, rhs)
@@ -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")
@@ -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
@@ -41,9 +39,7 @@ module Leftovers
41
39
  @exclude_paths
42
40
  @include_paths
43
41
  @test_paths
44
- @haml_paths
45
- @slim_paths
46
- @erb_paths
42
+ @precompilers
47
43
  @dynamic
48
44
  @keep
49
45
  @test_only
@@ -64,35 +60,11 @@ module Leftovers
64
60
  end
65
61
 
66
62
  def test_paths
67
- @test_paths ||= FastIgnore.new(
68
- include_rules: @configs.flat_map(&:test_paths),
69
- gitignore: false,
70
- root: Leftovers.pwd
71
- )
72
- end
73
-
74
- def haml_paths
75
- @haml_paths ||= FastIgnore.new(
76
- include_rules: @configs.flat_map(&:haml_paths),
77
- gitignore: false,
78
- root: Leftovers.pwd
79
- )
80
- end
81
-
82
- def slim_paths
83
- @slim_paths ||= FastIgnore.new(
84
- include_rules: @configs.flat_map(&:slim_paths),
85
- gitignore: false,
86
- root: Leftovers.pwd
87
- )
63
+ @test_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:test_paths))
88
64
  end
89
65
 
90
- def erb_paths
91
- @erb_paths ||= FastIgnore.new(
92
- include_rules: @configs.flat_map(&:erb_paths),
93
- gitignore: false,
94
- root: Leftovers.pwd
95
- )
66
+ def precompilers
67
+ @precompilers ||= Leftovers::Precompilers.build(@configs.flat_map(&:precompile))
96
68
  end
97
69
 
98
70
  def dynamic
@@ -109,6 +81,16 @@ module Leftovers
109
81
 
110
82
  private
111
83
 
84
+ def require_requires(config)
85
+ config.requires.each do |req|
86
+ if req.is_a?(Hash) && req[:quiet]
87
+ Leftovers.try_require(req[:quiet])
88
+ else
89
+ Leftovers.try_require(req, message: "cannot require '#{req}' from #{config.name}.yml")
90
+ end
91
+ end
92
+ end
93
+
112
94
  def load_bundled_gem_config
113
95
  return unless Leftovers.try_require('bundler')
114
96
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module Leftovers
6
+ module Precompilers
7
+ class ERB < ::ERB::Compiler
8
+ def self.precompile(erb)
9
+ @compiler ||= new('-')
10
+ @compiler.compile(erb).first
11
+ end
12
+
13
+ def add_insert_cmd(out, content) # leftovers:keep
14
+ out.push("\n#{content}\n")
15
+ end
16
+
17
+ def add_put_cmd(out, _content) # leftovers:keep
18
+ out.push("\n")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'haml'
4
+
5
+ module Leftovers
6
+ module Precompilers
7
+ module Haml
8
+ def self.precompile(haml)
9
+ ::Haml::Engine.new(haml).precompiled
10
+ rescue ::Haml::SyntaxError => e
11
+ raise Leftovers::PrecompileError.new(e.message, line: e.line)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Leftovers
6
+ module Precompilers
7
+ module JSON
8
+ class << self
9
+ def precompile(json)
10
+ "__leftovers_document(#{to_ruby_argument(::JSON.parse(json))})"
11
+ end
12
+
13
+ private
14
+
15
+ def to_ruby_argument(value)
16
+ ruby = value.inspect
17
+ return ruby unless value.is_a?(Array)
18
+
19
+ ruby.delete_prefix!('[')
20
+ ruby.delete_suffix!(']')
21
+
22
+ ruby
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Leftovers
6
+ module Precompilers
7
+ class Precompiler
8
+ def initialize(precompiler, matcher)
9
+ @precompiler = precompiler
10
+ @matcher = matcher
11
+ end
12
+
13
+ def precompile(content, file)
14
+ return unless @matcher === file.relative_path
15
+
16
+ begin
17
+ @precompiler.precompile(content)
18
+ rescue Leftovers::PrecompileError => e
19
+ e.warn(path: file.relative_path)
20
+ ''
21
+ rescue StandardError => e
22
+ Leftovers.warn "#{e.class}: #{file.relative_path} #{e.message}"
23
+ ''
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'slim'
4
+
5
+ module Leftovers
6
+ module Precompilers
7
+ module Slim
8
+ def self.precompile(file)
9
+ ::Slim::Engine.new(file: file).call(file)
10
+ rescue ::Slim::Parser::SyntaxError => e
11
+ raise Leftovers::PrecompileError.new(e.error, line: e.lineno, column: e.column)
12
+ end
13
+ end
14
+ end
15
+ end