leftovers 0.2.3 → 0.4.3

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