leftovers 0.6.0 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -3
- data/docs/Configuration.md +82 -18
- data/leftovers.gemspec +1 -1
- data/lib/config/actionmailer.yml +11 -11
- data/lib/config/activesupport.yml +1 -1
- data/lib/config/rails.yml +1 -1
- data/lib/config/railties.yml +11 -0
- data/lib/config/ruby.yml +72 -0
- data/lib/leftovers/ast/node.rb +16 -11
- data/lib/leftovers/config.rb +1 -24
- data/lib/leftovers/config_loader/argument_position_schema.rb +11 -0
- data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
- data/lib/leftovers/config_loader/attribute.rb +30 -0
- data/lib/leftovers/config_loader/document_schema.rb +21 -0
- data/lib/leftovers/config_loader/dynamic_schema.rb +17 -0
- data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
- data/lib/leftovers/config_loader/has_value_schema.rb +18 -0
- data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
- data/lib/leftovers/config_loader/node.rb +106 -0
- data/lib/leftovers/config_loader/object_schema.rb +189 -0
- data/lib/leftovers/config_loader/privacy_processor_schema.rb +12 -0
- data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
- data/lib/leftovers/config_loader/require_schema.rb +11 -0
- data/lib/leftovers/config_loader/rule_pattern_schema.rb +18 -0
- data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
- data/lib/leftovers/config_loader/scalar_value_schema.rb +14 -0
- data/lib/leftovers/config_loader/schema.rb +21 -0
- data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
- data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
- data/lib/leftovers/config_loader/string_schema.rb +14 -0
- data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
- data/lib/leftovers/config_loader/suggester.rb +22 -0
- data/lib/leftovers/config_loader/transform_schema.rb +28 -0
- data/lib/leftovers/config_loader/true_schema.rb +18 -0
- data/lib/leftovers/config_loader/value_matcher_schema.rb +18 -0
- data/lib/leftovers/config_loader/value_or_array_schema.rb +64 -0
- data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
- data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
- data/lib/leftovers/config_loader.rb +82 -0
- data/lib/leftovers/definition_node.rb +6 -17
- data/lib/leftovers/definition_node_set.rb +11 -0
- data/lib/leftovers/definition_to_add.rb +31 -0
- data/lib/leftovers/dynamic_processors/call.rb +4 -3
- data/lib/leftovers/dynamic_processors/call_definition.rb +14 -7
- data/lib/leftovers/dynamic_processors/definition.rb +8 -3
- data/lib/leftovers/dynamic_processors/set_default_privacy.rb +18 -0
- data/lib/leftovers/dynamic_processors/set_privacy.rb +23 -0
- data/lib/leftovers/dynamic_processors.rb +2 -0
- data/lib/leftovers/file.rb +5 -1
- data/lib/leftovers/file_collector.rb +44 -17
- data/lib/leftovers/matcher_builders/node.rb +4 -0
- data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
- data/lib/leftovers/matcher_builders/node_type.rb +4 -4
- data/lib/leftovers/matcher_builders/node_value.rb +1 -1
- data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
- data/lib/leftovers/matcher_builders.rb +1 -0
- data/lib/leftovers/matchers/node_privacy.rb +19 -0
- data/lib/leftovers/matchers.rb +1 -0
- data/lib/leftovers/merged_config.rb +18 -34
- data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
- data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
- data/lib/leftovers/processor_builders/dynamic.rb +50 -16
- data/lib/leftovers/processor_builders/transform.rb +2 -2
- data/lib/leftovers/processor_builders/transform_set.rb +8 -8
- data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
- data/lib/leftovers/value_processors/each_positional_argument.rb +1 -1
- data/lib/leftovers/value_processors/return_definition_node.rb +14 -0
- data/lib/leftovers/value_processors/{return_string.rb → return_sym.rb} +1 -1
- data/lib/leftovers/value_processors.rb +2 -2
- data/lib/leftovers/version.rb +1 -1
- data/lib/leftovers.rb +23 -14
- metadata +54 -22
- data/lib/config/actioncable.yml +0 -4
- data/lib/leftovers/config_validator/error_processor.rb +0 -196
- data/lib/leftovers/config_validator/schema_hash.rb +0 -551
- data/lib/leftovers/config_validator.rb +0 -61
- 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 :
|
5
|
+
attr_reader :name, :loc, :node
|
8
6
|
|
9
|
-
def initialize(
|
7
|
+
def initialize(node, name:, location: node.loc.expression)
|
8
|
+
@node = node
|
10
9
|
@name = name
|
11
|
-
@
|
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
|
-
|
26
|
-
|
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,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
|
-
|
15
|
-
return unless call
|
14
|
+
calls = @processor.process(nil, node, node)
|
16
15
|
|
17
|
-
|
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
|
-
|
16
|
-
(file.calls << call) if call
|
15
|
+
calls = @call_processor.process(nil, node, node)
|
17
16
|
|
18
|
-
|
17
|
+
::Leftovers.each_or_self(calls) do |call|
|
18
|
+
file.calls << call
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
return unless definition
|
21
|
+
return if node.keep_line?
|
22
22
|
|
23
|
-
|
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
|
-
|
16
|
-
return unless definition
|
15
|
+
definitions = @processor.process(nil, node, node)
|
17
16
|
|
18
|
-
|
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
|
data/lib/leftovers/file.rb
CHANGED
@@ -5,7 +5,11 @@ require 'pathname'
|
|
5
5
|
module Leftovers
|
6
6
|
class File < Pathname
|
7
7
|
def relative_path
|
8
|
-
@relative_path ||=
|
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
|
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
|
-
@
|
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
|
-
|
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
|
190
|
-
@
|
191
|
-
|
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
|
195
|
-
|
206
|
+
def set_privacy(name, to)
|
207
|
+
@definitions_to_add[name]&.privacy = to
|
196
208
|
end
|
197
209
|
|
198
|
-
def
|
199
|
-
|
200
|
-
|
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
|
-
|
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)
|
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
|
-
|
20
|
-
|
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
|
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
|
19
|
+
/\A(?=#{has_prefix}).*#{has_suffix}\z/
|
11
20
|
elsif has_prefix
|
12
|
-
/\A#{
|
21
|
+
/\A#{has_prefix}/
|
13
22
|
elsif has_suffix
|
14
|
-
/#{
|
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
|
data/lib/leftovers/matchers.rb
CHANGED
@@ -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
|
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
|
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 ||=
|
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 ||=
|
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 ||=
|
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 ||=
|
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 ||=
|
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 ||=
|
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
|
|