leftovers 0.2.3 → 0.4.3

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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/README.md +65 -49
  4. data/docs/Configuration.md +627 -0
  5. data/exe/leftovers +2 -2
  6. data/leftovers.gemspec +13 -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 +126 -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 +42 -49
  19. data/lib/config/selenium-webdriver.yml +19 -0
  20. data/lib/config/sidekiq.yml +4 -8
  21. data/lib/config/will_paginate.yml +12 -14
  22. data/lib/leftovers.rb +66 -54
  23. data/lib/leftovers/ast.rb +8 -0
  24. data/lib/leftovers/ast/builder.rb +6 -3
  25. data/lib/leftovers/ast/node.rb +66 -107
  26. data/lib/leftovers/backports.rb +24 -40
  27. data/lib/leftovers/cli.rb +27 -15
  28. data/lib/leftovers/collector.rb +8 -11
  29. data/lib/leftovers/config.rb +38 -13
  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 +496 -0
  33. data/lib/leftovers/definition.rb +16 -41
  34. data/lib/leftovers/definition_node.rb +36 -0
  35. data/lib/leftovers/definition_set.rb +17 -24
  36. data/lib/leftovers/dynamic_processors.rb +11 -0
  37. data/lib/leftovers/dynamic_processors/call.rb +25 -0
  38. data/lib/leftovers/dynamic_processors/call_definition.rb +31 -0
  39. data/lib/leftovers/dynamic_processors/definition.rb +26 -0
  40. data/lib/leftovers/dynamic_processors/each.rb +19 -0
  41. data/lib/leftovers/dynamic_processors/null.rb +9 -0
  42. data/lib/leftovers/erb.rb +2 -2
  43. data/lib/leftovers/file.rb +3 -5
  44. data/lib/leftovers/file_collector.rb +79 -61
  45. data/lib/leftovers/file_list.rb +9 -15
  46. data/lib/leftovers/haml.rb +9 -12
  47. data/lib/leftovers/matcher_builders.rb +24 -0
  48. data/lib/leftovers/matcher_builders/and.rb +19 -0
  49. data/lib/leftovers/matcher_builders/and_not.rb +14 -0
  50. data/lib/leftovers/matcher_builders/argument_node_value.rb +21 -0
  51. data/lib/leftovers/matcher_builders/name.rb +29 -0
  52. data/lib/leftovers/matcher_builders/node.rb +40 -0
  53. data/lib/leftovers/matcher_builders/node_has_argument.rb +71 -0
  54. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +22 -0
  55. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +24 -0
  56. data/lib/leftovers/matcher_builders/node_name.rb +15 -0
  57. data/lib/leftovers/matcher_builders/node_pair_name.rb +18 -0
  58. data/lib/leftovers/matcher_builders/node_pair_value.rb +16 -0
  59. data/lib/leftovers/matcher_builders/node_path.rb +14 -0
  60. data/lib/leftovers/matcher_builders/node_type.rb +28 -0
  61. data/lib/leftovers/matcher_builders/or.rb +73 -0
  62. data/lib/leftovers/matcher_builders/path.rb +15 -0
  63. data/lib/leftovers/matcher_builders/string.rb +11 -0
  64. data/lib/leftovers/matcher_builders/string_pattern.rb +19 -0
  65. data/lib/leftovers/matcher_builders/unless.rb +13 -0
  66. data/lib/leftovers/matchers.rb +26 -0
  67. data/lib/leftovers/matchers/all.rb +25 -0
  68. data/lib/leftovers/matchers/and.rb +24 -0
  69. data/lib/leftovers/matchers/any.rb +27 -0
  70. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +28 -0
  71. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +25 -0
  72. data/lib/leftovers/matchers/node_has_positional_argument.rb +23 -0
  73. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +25 -0
  74. data/lib/leftovers/matchers/node_name.rb +23 -0
  75. data/lib/leftovers/matchers/node_pair_value.rb +23 -0
  76. data/lib/leftovers/matchers/node_path.rb +23 -0
  77. data/lib/leftovers/matchers/node_scalar_value.rb +25 -0
  78. data/lib/leftovers/matchers/node_type.rb +23 -0
  79. data/lib/leftovers/matchers/not.rb +23 -0
  80. data/lib/leftovers/matchers/or.rb +26 -0
  81. data/lib/leftovers/merged_config.rb +29 -14
  82. data/lib/leftovers/parser.rb +1 -4
  83. data/lib/leftovers/processor_builders.rb +22 -0
  84. data/lib/leftovers/processor_builders/action.rb +63 -0
  85. data/lib/leftovers/processor_builders/add_prefix.rb +20 -0
  86. data/lib/leftovers/processor_builders/add_suffix.rb +20 -0
  87. data/lib/leftovers/processor_builders/argument.rb +25 -0
  88. data/lib/leftovers/processor_builders/dynamic.rb +27 -0
  89. data/lib/leftovers/processor_builders/each.rb +36 -0
  90. data/lib/leftovers/processor_builders/each_action.rb +51 -0
  91. data/lib/leftovers/processor_builders/each_dynamic.rb +54 -0
  92. data/lib/leftovers/processor_builders/each_for_definition_set.rb +36 -0
  93. data/lib/leftovers/processor_builders/itself.rb +13 -0
  94. data/lib/leftovers/processor_builders/keyword.rb +24 -0
  95. data/lib/leftovers/processor_builders/keyword_argument.rb +14 -0
  96. data/lib/leftovers/processor_builders/transform.rb +55 -0
  97. data/lib/leftovers/processor_builders/transform_chain.rb +24 -0
  98. data/lib/leftovers/processor_builders/transform_set.rb +47 -0
  99. data/lib/leftovers/processor_builders/value.rb +13 -0
  100. data/lib/leftovers/rake_task.rb +4 -4
  101. data/lib/leftovers/reporter.rb +56 -4
  102. data/lib/leftovers/todo_reporter.rb +124 -0
  103. data/lib/leftovers/value_processors.rb +40 -0
  104. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +31 -0
  105. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +31 -0
  106. data/lib/leftovers/value_processors/add_prefix.rb +20 -0
  107. data/lib/leftovers/value_processors/add_suffix.rb +20 -0
  108. data/lib/leftovers/value_processors/camelize.rb +24 -0
  109. data/lib/leftovers/value_processors/capitalize.rb +19 -0
  110. data/lib/leftovers/value_processors/deconstantize.rb +24 -0
  111. data/lib/leftovers/value_processors/delete_after.rb +22 -0
  112. data/lib/leftovers/value_processors/delete_before.rb +22 -0
  113. data/lib/leftovers/value_processors/delete_prefix.rb +26 -0
  114. data/lib/leftovers/value_processors/delete_suffix.rb +26 -0
  115. data/lib/leftovers/value_processors/demodulize.rb +24 -0
  116. data/lib/leftovers/value_processors/downcase.rb +19 -0
  117. data/lib/leftovers/value_processors/each.rb +21 -0
  118. data/lib/leftovers/value_processors/each_for_definition_set.rb +29 -0
  119. data/lib/leftovers/value_processors/each_keyword.rb +27 -0
  120. data/lib/leftovers/value_processors/each_keyword_argument.rb +27 -0
  121. data/lib/leftovers/value_processors/each_positional_argument.rb +24 -0
  122. data/lib/leftovers/value_processors/itself.rb +17 -0
  123. data/lib/leftovers/value_processors/keyword.rb +36 -0
  124. data/lib/leftovers/value_processors/keyword_argument.rb +36 -0
  125. data/lib/leftovers/value_processors/parameterize.rb +24 -0
  126. data/lib/leftovers/value_processors/placeholder.rb +18 -0
  127. data/lib/leftovers/value_processors/pluralize.rb +24 -0
  128. data/lib/leftovers/value_processors/positional_argument.rb +26 -0
  129. data/lib/leftovers/value_processors/replace_value.rb +18 -0
  130. data/lib/leftovers/value_processors/return_definition.rb +26 -0
  131. data/lib/leftovers/value_processors/return_string.rb +14 -0
  132. data/lib/leftovers/value_processors/singularize.rb +24 -0
  133. data/lib/leftovers/value_processors/split.rb +22 -0
  134. data/lib/leftovers/value_processors/swapcase.rb +19 -0
  135. data/lib/leftovers/value_processors/titleize.rb +24 -0
  136. data/lib/leftovers/value_processors/underscore.rb +24 -0
  137. data/lib/leftovers/value_processors/upcase.rb +19 -0
  138. data/lib/leftovers/version.rb +1 -1
  139. metadata +201 -25
  140. data/lib/config/selenium.yml +0 -21
  141. data/lib/leftovers/argument_rule.rb +0 -219
  142. data/lib/leftovers/core_ext.rb +0 -13
  143. data/lib/leftovers/hash_rule.rb +0 -40
  144. data/lib/leftovers/name_rule.rb +0 -53
  145. data/lib/leftovers/rule.rb +0 -74
  146. data/lib/leftovers/transform_rule.rb +0 -171
  147. data/lib/leftovers/value_rule.rb +0 -56
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'set'
4
-
5
- class Array
6
- def leftovers_append(other)
7
- case other
8
- when Array, Set then concat(other)
9
- when nil then self
10
- else self.<< other
11
- end
12
- end
13
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'set'
4
- require_relative 'value_rule'
5
- require_relative 'name_rule'
6
-
7
- module Leftovers
8
- class HashRule
9
- def initialize(patterns) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
10
- keys = []
11
- pairs = []
12
- Leftovers.each_or_self(patterns) do |pat|
13
- if pat.is_a?(Hash) && pat[:value]
14
- pairs << [
15
- (NameRule.new(pat[:keyword]) if pat[:keyword]),
16
- (ValueRule.new(pat[:value]) if pat[:value])
17
- ]
18
- else
19
- keys << NameRule.new(pat)
20
- end
21
- end
22
-
23
- @keys = (NameRule.new(keys) if keys)
24
-
25
- @pairs = (pairs unless pairs.empty?)
26
-
27
- freeze
28
- end
29
-
30
- def match_pair?(key_node, value_node)
31
- return true if @keys&.match?(key_node.to_sym, key_node.to_s)
32
-
33
- @pairs&.any? do |(key_rule, value_rule)|
34
- next unless !key_rule || key_rule.match?(key_node.to_sym, key_node.to_s)
35
-
36
- (!value_rule || value_rule.match?(value_node))
37
- end
38
- end
39
- end
40
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'set'
4
- module Leftovers
5
- class NameRule
6
- attr_reader :sym, :syms, :regexp
7
-
8
- def initialize(patterns) # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
9
- regexps = []
10
- syms = Set.new
11
- Leftovers.each_or_self(patterns) do |pat|
12
- case pat
13
- when Leftovers::NameRule
14
- syms.merge(pat.sym) if pat.sym
15
- syms.merge(pat.syms) if pat.syms
16
- regexps.concat(pat.regexp) if pat.regexp
17
- when String
18
- syms.merge(pat.split(/\s+/).map(&:to_sym))
19
- when Hash
20
- if pat[:match]
21
- regexps << /\A#{pattern[:match]}\z/
22
- elsif pat[:has_prefix] && pat[:has_suffix]
23
- regexps << /\A#{Regexp.escape(pat[:has_prefix])}.*#{Regexp.escape(pat[:has_suffix])}\z/
24
- elsif pat[:has_prefix]
25
- regexps << /\A#{Regexp.escape(pat[:has_prefix])}/
26
- elsif pat[:has_suffix]
27
- regexps << /#{Regexp.escape(pat[:has_suffix])}\z/
28
- end
29
- end
30
- end
31
-
32
- if syms.length <= 0
33
- @sym = syms.first
34
- @syms = nil
35
- else
36
- @sym = nil
37
- @syms = syms
38
- end
39
-
40
- @regexp = if regexps.empty?
41
- nil
42
- else
43
- Regexp.union(regexps)
44
- end
45
-
46
- freeze
47
- end
48
-
49
- def match?(sym, string)
50
- @sym&.==(sym) || @syms&.include?(sym) || @regexp&.match?(string)
51
- end
52
- end
53
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'name_rule'
4
- require_relative 'argument_rule'
5
- require 'fast_ignore'
6
-
7
- module Leftovers
8
- class Rule
9
- def self.wrap(rules)
10
- case rules
11
- when Array then rules.flat_map { |r| wrap(r) }
12
- when nil then [].freeze
13
- else new(**rules)
14
- end
15
- end
16
-
17
- attr_reader :skip
18
- alias_method :skip?, :skip
19
-
20
- def initialize( # rubocop:disable Metrics/ParameterLists, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
21
- name: nil,
22
- names: nil,
23
- calls: nil,
24
- call: nil,
25
- skip: false,
26
- defines: nil,
27
- define: nil,
28
- path: nil,
29
- paths: nil
30
- )
31
- raise ArgumentError, 'Only use one of name/names' if name && names
32
- raise ArgumentError, 'Only use one of path/paths' if path && paths
33
- raise ArgumentError, 'Only use one of call/calls' if call && calls
34
- raise ArgumentError, 'Only use one of define/defines' if define && defines
35
- if skip && (defines || calls)
36
- raise ArgumentError, "skip can't exist with defines or calls for #{name || names}"
37
- end
38
-
39
- @name_matcher = NameRule.new(name || names)
40
- @path = FastIgnore.new(include_rules: path || paths, gitignore: false) if path || paths
41
- @skip = skip
42
-
43
- begin
44
- @calls = ArgumentRule.wrap(calls)
45
- rescue ArgumentError => e
46
- raise e, "#{e.message} for calls for #{name}", e.backtrace
47
- end
48
-
49
- begin
50
- @defines = ArgumentRule.wrap(defines, definer: true)
51
- rescue ArgumentError => e
52
- raise e, "#{e.message} for defines for #{name}", e.backtrace
53
- end
54
- end
55
-
56
- def filename?(file)
57
- return true unless @path
58
-
59
- @path.allowed?(file)
60
- end
61
-
62
- def match?(name, name_s, file)
63
- @name_matcher.match?(name, name_s) && filename?(file)
64
- end
65
-
66
- def calls(node)
67
- @calls.flat_map { |m| m.matches(node) }
68
- end
69
-
70
- def definitions(node)
71
- @defines.flat_map { |m| m.matches(node) }
72
- end
73
- end
74
- end
@@ -1,171 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Leftovers
4
- class TransformRule # rubocop:disable Metrics/ClassLength
5
- # :nocov:
6
- using ::Leftovers::StringDeletePrefixSuffix if defined?(::Leftovers::StringDeletePrefixSuffix)
7
- # :nocov:
8
-
9
- RUBY_STRING_METHODS = %i{
10
- downcase
11
- upcase
12
- capitalize
13
- swapcase
14
- }.freeze
15
-
16
- ACTIVESUPPORT_STRING_METHODS = %i{
17
- pluralize
18
- singularize
19
- camelize
20
- camelcase
21
- underscore
22
- titleize
23
- titlecase
24
- demodulize
25
- deconstantize
26
- parameterize
27
- }.freeze
28
-
29
- CUSTOM_TRANSFORMS = %i{
30
- original
31
- delete_before
32
- delete_after
33
- add_prefix
34
- add_suffix
35
- delete_prefix
36
- delete_suffix
37
- replace_with
38
- }.freeze
39
-
40
- VALID_TRANSFORMS = RUBY_STRING_METHODS + ACTIVESUPPORT_STRING_METHODS + CUSTOM_TRANSFORMS
41
- # more possible transformations
42
- # gsub sub tr tr_s
43
- def initialize(transforms)
44
- @transforms = prepare_transforms(transforms)
45
-
46
- freeze
47
- end
48
-
49
- def transform(original_string, method_node)
50
- string = original_string
51
- @transforms.each { |proc| string = proc.call(string, method_node) }
52
-
53
- string.to_sym
54
- end
55
-
56
- private
57
-
58
- def prepare_transforms(transforms) # rubocop:disable Metrics/MethodLength
59
- transforms.map do |key, value|
60
- unless VALID_TRANSFORMS.include?(key)
61
- raise ArgumentError, <<~MESSAGE
62
- invalid transform key: (#{key}: #{value}).
63
- Valid transform keys are #{ALL_VALID_TRANSFORMS}"
64
- MESSAGE
65
- end
66
-
67
- key, value = prepare_hash_value(key, value) if value.is_a?(Hash)
68
-
69
- instance_variable_set(:"@#{key}", value.freeze)
70
- method(key)
71
- end
72
- end
73
-
74
- HASH_VALUE_TRANSFORMS = %i{add_prefix add_suffix}.freeze
75
- HASH_VALUE_KEYS = %i{from_argument joiner}.freeze
76
- def prepare_hash_value(method, hash) # rubocop:disable Metrics/MethodLength
77
- raise ArgumentError, <<~MESSAGE unless HASH_VALUE_TRANSFORMS.include?(method)
78
- invalid transform value (#{key}: #{value}).
79
- Hash values are only valid for #{HASH_VALUE_TRANSFORMS}
80
- MESSAGE
81
-
82
- hash = hash.map do |k, v|
83
- raise ArgumentError, <<~MESSAGE unless HASH_VALUE_KEYS.include?(k)
84
- invalid transform value argument (#{method}: { #{k}: #{v} }).
85
- Hash values are only valid for #{HASH_VALUE_TRANSFORMS}
86
- MESSAGE
87
-
88
- [k, v.to_sym]
89
- end.to_h
90
-
91
- ["#{method}_dynamic", hash]
92
- end
93
-
94
- RUBY_STRING_METHODS.each do |method|
95
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
96
- def #{method}(string, _method_node)
97
- string.#{method}
98
- end
99
- RUBY
100
- end
101
-
102
- # leftovers:call activesupport_available?
103
- ACTIVESUPPORT_STRING_METHODS.each do |method|
104
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
105
- def #{method}(string, _method_node)
106
- return string unless activesupport_available?(:#{method})
107
-
108
- string.#{method}
109
- end
110
- RUBY
111
- end
112
-
113
- def original(string, _method_node)
114
- string
115
- end
116
-
117
- def delete_prefix(string, _method_node)
118
- string.delete_prefix(@delete_prefix)
119
- end
120
-
121
- def delete_suffix(string, _method_node)
122
- string.delete_suffix(@delete_suffix)
123
- end
124
-
125
- def delete_before(string, _method_node)
126
- string.split(@delete_before, 2)[1] || string
127
- end
128
-
129
- def delete_after(string, _method_node)
130
- string.split(@delete_after, 2).first || string
131
- end
132
-
133
- def replace_with(_string, _method_node)
134
- @replace_with
135
- end
136
-
137
- def add_prefix(string, _method_node)
138
- "#{@add_prefix}#{string}"
139
- end
140
-
141
- def add_suffix(string, _method_node)
142
- "#{string}#{@add_suffix}"
143
- end
144
-
145
- def add_prefix_dynamic(string, method_node)
146
- "#{dynamic_value(@add_prefix_dynamic, method_node)}#{@add_prefix_dynamic[:joiner]}#{string}"
147
- end
148
-
149
- def add_suffix_dynamic(string, method_node)
150
- "#{string}#{@add_suffix_dynamic[:joiner]}#{dynamic_value(@add_suffix_dynamic, method_node)}"
151
- end
152
-
153
- def dynamic_value(value, method_node)
154
- method_node.kwargs[value[:from_argument]].to_s if value[:from_argument]
155
- end
156
-
157
- def activesupport_available?(method) # rubocop:disable Metrics/MethodLength
158
- Leftovers.try_require(
159
- 'active_support/core_ext/string', 'active_support/inflections',
160
- message: <<~MESSAGE
161
- Tried transforming a string using an activesupport method (#{method}), but the activesupport gem was not available
162
- `gem install activesupport`
163
- MESSAGE
164
- )
165
-
166
- Leftovers.try_require(::File.join(Leftovers.pwd, 'config', 'initializers', 'inflections.rb'))
167
-
168
- defined?(ActiveSupport)
169
- end
170
- end
171
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Leftovers
4
- class ValueRule
5
- def initialize(values) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
6
- literal_values = Set.new
7
- value_types = Set.new
8
-
9
- Leftovers.each_or_self(values) do |value|
10
- case value
11
- when Hash
12
- raise ArgumentError, "invalid value #{value.inspect}" unless value[:type]
13
-
14
- value_types.merge(
15
- Array(value[:type]).map do |v|
16
- case v
17
- when 'String', :String then :str
18
- when 'Symbol', :Symbol then :sym
19
- else v.to_s.downcase.to_sym
20
- end
21
- end
22
- )
23
- else
24
- (literal_values << value) if value
25
- end
26
- end
27
-
28
- if literal_values.length <= 1
29
- @literal_value = literal_values.first
30
- @literal_values = nil
31
- else
32
- @literal_value = nil
33
- @literal_values = literal_values
34
- end
35
-
36
- if value_types.length <= 1
37
- @value_type = value_types.first
38
- @value_types = nil
39
- else
40
- @value_type = nil
41
- @value_types = value_types
42
- end
43
-
44
- freeze
45
- end
46
-
47
- def match?(value_node) # rubocop:disable Metrics/CyclomaticComplexity
48
- return true if @value_type&.== value_node.type
49
- return true if @value_types&.include?(value_node.type)
50
- return false unless (@literal_value || @literal_values) && value_node.scalar?
51
- return true if @literal_value&.== value_node.to_scalar_value
52
-
53
- @literal_values&.include?(value_node.to_scalar_value)
54
- end
55
- end
56
- end