leftovers 0.5.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +21 -1
- data/docs/Configuration.md +106 -2
- data/leftovers.gemspec +7 -4
- data/lib/config/ruby.yml +7 -0
- data/lib/leftovers/collector.rb +3 -1
- data/lib/leftovers/config.rb +8 -4
- data/lib/leftovers/config_validator/schema_hash.rb +170 -149
- data/lib/leftovers/config_validator.rb +1 -0
- data/lib/leftovers/definition.rb +1 -1
- data/lib/leftovers/dynamic_processors/call.rb +0 -4
- data/lib/leftovers/dynamic_processors/call_definition.rb +0 -4
- data/lib/leftovers/dynamic_processors/definition.rb +0 -4
- data/lib/leftovers/file.rb +52 -10
- data/lib/leftovers/file_collector.rb +33 -2
- data/lib/leftovers/json.rb +28 -0
- data/lib/leftovers/matcher_builders/document.rb +13 -0
- data/lib/leftovers/matcher_builders/node.rb +3 -1
- data/lib/leftovers/matcher_builders/node_has_argument.rb +3 -4
- data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +1 -1
- data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +1 -1
- data/lib/leftovers/matcher_builders.rb +1 -0
- data/lib/leftovers/matchers/all.rb +0 -4
- data/lib/leftovers/matchers/and.rb +0 -4
- data/lib/leftovers/matchers/any.rb +0 -4
- data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +1 -7
- data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +1 -7
- data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +0 -4
- data/lib/leftovers/matchers/node_name.rb +0 -4
- data/lib/leftovers/matchers/node_pair_value.rb +0 -4
- data/lib/leftovers/matchers/node_path.rb +0 -4
- data/lib/leftovers/matchers/node_scalar_value.rb +0 -4
- data/lib/leftovers/matchers/node_type.rb +0 -4
- data/lib/leftovers/matchers/not.rb +0 -4
- data/lib/leftovers/matchers/or.rb +0 -4
- data/lib/leftovers/merged_config.rb +19 -1
- data/lib/leftovers/processor_builders/dynamic.rb +2 -1
- data/lib/leftovers/todo_reporter.rb +10 -35
- data/lib/leftovers/value_processors/delete_prefix.rb +0 -6
- data/lib/leftovers/value_processors/delete_suffix.rb +0 -6
- data/lib/leftovers/value_processors/keyword.rb +0 -4
- data/lib/leftovers/value_processors/keyword_argument.rb +0 -4
- data/lib/leftovers/value_processors/return_definition.rb +0 -4
- data/lib/leftovers/version.rb +1 -1
- data/lib/leftovers/yaml.rb +73 -0
- data/lib/leftovers.rb +6 -7
- metadata +33 -16
- data/lib/leftovers/backports.rb +0 -40
@@ -10,7 +10,7 @@ module Leftovers
|
|
10
10
|
::Leftovers::MatcherBuilders::NodeName.build(pat)
|
11
11
|
when ::Hash
|
12
12
|
build_from_hash(**pat)
|
13
|
-
|
13
|
+
# :nocov:
|
14
14
|
else raise
|
15
15
|
# :nocov:
|
16
16
|
end
|
@@ -19,6 +19,7 @@ module Leftovers
|
|
19
19
|
|
20
20
|
def self.build_from_hash( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
21
21
|
names: nil, match: nil, has_prefix: nil, has_suffix: nil,
|
22
|
+
document: false,
|
22
23
|
paths: nil,
|
23
24
|
has_arguments: nil,
|
24
25
|
has_receiver: nil,
|
@@ -29,6 +30,7 @@ module Leftovers
|
|
29
30
|
names,
|
30
31
|
{ match: match, has_prefix: has_prefix, has_suffix: has_suffix }.compact
|
31
32
|
]),
|
33
|
+
::Leftovers::MatcherBuilders::Document.build(document),
|
32
34
|
::Leftovers::MatcherBuilders::NodePath.build(paths),
|
33
35
|
::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
|
34
36
|
::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
|
@@ -26,12 +26,10 @@ module Leftovers
|
|
26
26
|
|
27
27
|
::Leftovers.each_or_self(at) do |k|
|
28
28
|
case k
|
29
|
-
when '*'
|
29
|
+
when '*', ::Integer
|
30
30
|
positions << k
|
31
31
|
when ::String, ::Hash
|
32
32
|
keys << k
|
33
|
-
when ::Integer
|
34
|
-
positions << k
|
35
33
|
# :nocov:
|
36
34
|
else raise
|
37
35
|
# :nocov:
|
@@ -62,7 +60,8 @@ module Leftovers
|
|
62
60
|
elsif positions
|
63
61
|
::Leftovers::MatcherBuilders::NodeHasPositionalArgument.build(positions, value_matcher)
|
64
62
|
# :nocov:
|
65
|
-
else
|
63
|
+
else
|
64
|
+
raise
|
66
65
|
# :nocov:
|
67
66
|
end
|
68
67
|
|
@@ -6,7 +6,7 @@ module Leftovers
|
|
6
6
|
class << self
|
7
7
|
def build(keywords, value_matcher) # rubocop:disable Metrics/MethodLength
|
8
8
|
value_matcher = ::Leftovers::MatcherBuilders::NodePairValue.build(value_matcher)
|
9
|
-
keyword_matcher = if ::Leftovers.each_or_self(keywords).
|
9
|
+
keyword_matcher = if ::Leftovers.each_or_self(keywords).include?('**')
|
10
10
|
::Leftovers::Matchers::NodeType.new(:pair)
|
11
11
|
else
|
12
12
|
::Leftovers::MatcherBuilders::NodePairName.build(keywords)
|
@@ -14,7 +14,7 @@ module Leftovers
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
elsif positions
|
17
|
-
pos = 0 if ::Leftovers.each_or_self(positions).
|
17
|
+
pos = 0 if ::Leftovers.each_or_self(positions).include?('*')
|
18
18
|
pos ||= ::Leftovers.each_or_self(positions).min
|
19
19
|
|
20
20
|
::Leftovers::Matchers::NodeHasPositionalArgument.new(pos)
|
@@ -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")
|
@@ -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?
|
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?
|
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
|
@@ -4,7 +4,7 @@ require 'set'
|
|
4
4
|
require 'fast_ignore'
|
5
5
|
|
6
6
|
module Leftovers
|
7
|
-
class MergedConfig
|
7
|
+
class MergedConfig # rubocop:disable Metrics/ClassLength
|
8
8
|
def initialize(load_defaults: false)
|
9
9
|
@configs = []
|
10
10
|
@loaded_configs = Set.new
|
@@ -43,6 +43,8 @@ module Leftovers
|
|
43
43
|
@test_paths
|
44
44
|
@haml_paths
|
45
45
|
@slim_paths
|
46
|
+
@yaml_paths
|
47
|
+
@json_paths
|
46
48
|
@erb_paths
|
47
49
|
@dynamic
|
48
50
|
@keep
|
@@ -87,6 +89,22 @@ module Leftovers
|
|
87
89
|
)
|
88
90
|
end
|
89
91
|
|
92
|
+
def yaml_paths
|
93
|
+
@yaml_paths ||= FastIgnore.new(
|
94
|
+
include_rules: @configs.flat_map(&:yaml_paths),
|
95
|
+
gitignore: false,
|
96
|
+
root: Leftovers.pwd
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
def json_paths
|
101
|
+
@json_paths ||= FastIgnore.new(
|
102
|
+
include_rules: @configs.flat_map(&:json_paths),
|
103
|
+
gitignore: false,
|
104
|
+
root: Leftovers.pwd
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
90
108
|
def erb_paths
|
91
109
|
@erb_paths ||= FastIgnore.new(
|
92
110
|
include_rules: @configs.flat_map(&:erb_paths),
|
@@ -64,54 +64,29 @@ module Leftovers
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def todo_data(only_test, none)
|
67
|
-
none_test = none.select(&:test?)
|
68
|
-
none_non_test = none.reject(&:test?)
|
69
67
|
[
|
70
|
-
|
71
|
-
|
68
|
+
list_data(
|
69
|
+
:test_only, 'Only directly called in tests', only_test
|
70
|
+
),
|
71
|
+
list_data(
|
72
|
+
:keep, 'Not directly called at all', none
|
73
|
+
)
|
72
74
|
].compact.join
|
73
75
|
end
|
74
76
|
|
75
|
-
def
|
77
|
+
def list_data(key, title, list)
|
76
78
|
return if list.empty?
|
77
79
|
|
78
80
|
<<~YML
|
79
|
-
|
80
|
-
|
81
|
-
YML
|
82
|
-
end
|
83
|
-
|
84
|
-
def keep_data(only_test, none_non_test)
|
85
|
-
return if only_test.empty? && none_non_test.empty?
|
86
|
-
|
87
|
-
<<~YML.chomp
|
88
|
-
keep:
|
89
|
-
#{keep_test_called_data(only_test)}#{keep_never_called_data(none_non_test)}
|
90
|
-
YML
|
91
|
-
end
|
92
|
-
|
93
|
-
def keep_test_called_data(list)
|
94
|
-
return if list.empty?
|
95
|
-
|
96
|
-
generate_list('Only directly called in tests:', list)
|
97
|
-
end
|
98
|
-
|
99
|
-
def keep_never_called_data(list)
|
100
|
-
return if list.empty?
|
101
|
-
|
102
|
-
generate_list('Not directly called at all:', list)
|
103
|
-
end
|
104
|
-
|
105
|
-
def generate_list(title, list)
|
106
|
-
<<~YML
|
107
|
-
# #{title}
|
81
|
+
#{key}:
|
82
|
+
# #{title}:
|
108
83
|
#{print_definition_list(list)}
|
109
84
|
|
110
85
|
YML
|
111
86
|
end
|
112
87
|
|
113
88
|
def print_definition_list(definition_list)
|
114
|
-
definition_list.map { |definition| print_definition(definition) }.join("\n")
|
89
|
+
definition_list.map { |definition| print_definition(definition) }.sort.join("\n")
|
115
90
|
end
|
116
91
|
|
117
92
|
def print_definition(definition)
|
@@ -3,12 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
class DeletePrefix
|
6
|
-
# :nocov:
|
7
|
-
if defined?(::Leftovers::Backports::StringDeletePrefixSuffix)
|
8
|
-
using ::Leftovers::Backports::StringDeletePrefixSuffix
|
9
|
-
end
|
10
|
-
# :nocov:
|
11
|
-
|
12
6
|
def initialize(prefix, then_processor)
|
13
7
|
@prefix = prefix
|
14
8
|
@then_processor = then_processor
|
@@ -3,12 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
class DeleteSuffix
|
6
|
-
# :nocov:
|
7
|
-
if defined?(::Leftovers::Backports::StringDeletePrefixSuffix)
|
8
|
-
using ::Leftovers::Backports::StringDeletePrefixSuffix
|
9
|
-
end
|
10
|
-
# :nocov:
|
11
|
-
|
12
6
|
def initialize(suffix, then_processor)
|
13
7
|
@suffix = suffix
|
14
8
|
@then_processor = then_processor
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
class Keyword
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def initialize(matcher, then_processor)
|
11
7
|
@matcher = matcher
|
12
8
|
@then_processor = then_processor
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
class KeywordArgument
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def initialize(matcher, then_processor)
|
11
7
|
@matcher = matcher
|
12
8
|
@then_processor = then_processor
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
module ReturnDefinition
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def self.process(str, node, method_node)
|
11
7
|
return unless str
|
12
8
|
return if str.empty?
|
data/lib/leftovers/version.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
module YAML
|
7
|
+
class Builder < ::Psych::TreeBuilder
|
8
|
+
def initialize
|
9
|
+
@constants = []
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_constant_for_tag(tag, value = nil)
|
15
|
+
match = %r{\A!ruby/[^:]*(?::(.*))?\z}.match(tag)
|
16
|
+
return unless match
|
17
|
+
|
18
|
+
@constants << (match[1] || value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_mapping(_anchor, tag, *rest) # leftovers:keep
|
22
|
+
add_constant_for_tag(tag)
|
23
|
+
tag = nil
|
24
|
+
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def start_sequence(_anchor, tag, *rest) # leftovers:keep
|
29
|
+
add_constant_for_tag(tag)
|
30
|
+
tag = nil
|
31
|
+
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def scalar(value, _anchor, tag, *rest) # leftovers:keep
|
36
|
+
add_constant_for_tag(tag, value)
|
37
|
+
tag = nil
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_ruby_file
|
43
|
+
<<~RUBY
|
44
|
+
__leftovers_document(#{to_ruby_argument(root.to_ruby.first)})
|
45
|
+
#{@constants.join("\n")}
|
46
|
+
RUBY
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def to_ruby_argument(value)
|
52
|
+
ruby = value.inspect
|
53
|
+
return ruby unless value.is_a?(Array)
|
54
|
+
|
55
|
+
ruby.delete_prefix!('[')
|
56
|
+
ruby.delete_suffix!(']')
|
57
|
+
|
58
|
+
ruby
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.precompile(yaml, name)
|
63
|
+
builder = ::Leftovers::YAML::Builder.new
|
64
|
+
parser = ::Psych::Parser.new(builder)
|
65
|
+
parser.parse(yaml, name.relative_path)
|
66
|
+
|
67
|
+
builder.to_ruby_file
|
68
|
+
rescue ::Psych::SyntaxError => e
|
69
|
+
Leftovers.warn "#{e.class}: #{e.message}"
|
70
|
+
''
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/leftovers.rb
CHANGED
@@ -4,7 +4,6 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
|
|
4
4
|
class Error < ::StandardError; end
|
5
5
|
|
6
6
|
autoload(:AST, "#{__dir__}/leftovers/ast")
|
7
|
-
autoload(:Backports, "#{__dir__}/leftovers/backports")
|
8
7
|
autoload(:CLI, "#{__dir__}/leftovers/cli")
|
9
8
|
autoload(:Collector, "#{__dir__}/leftovers/collector")
|
10
9
|
autoload(:ConfigValidator, "#{__dir__}/leftovers/config_validator")
|
@@ -17,6 +16,8 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
|
|
17
16
|
autoload(:FileList, "#{__dir__}/leftovers/file_list")
|
18
17
|
autoload(:File, "#{__dir__}/leftovers/file")
|
19
18
|
autoload(:Haml, "#{__dir__}/leftovers/haml")
|
19
|
+
autoload(:YAML, "#{__dir__}/leftovers/yaml")
|
20
|
+
autoload(:JSON, "#{__dir__}/leftovers/json")
|
20
21
|
autoload(:MatcherBuilders, "#{__dir__}/leftovers/matcher_builders")
|
21
22
|
autoload(:Matchers, "#{__dir__}/leftovers/matchers")
|
22
23
|
autoload(:MergedConfig, "#{__dir__}/leftovers/merged_config")
|
@@ -147,12 +148,10 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
|
|
147
148
|
@try_require_cache ||= {}
|
148
149
|
|
149
150
|
@try_require_cache.fetch(requirable) do
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
@try_require_cache[requirable] = false
|
155
|
-
end
|
151
|
+
require requirable
|
152
|
+
@try_require_cache[requirable] = true
|
153
|
+
rescue LoadError
|
154
|
+
@try_require_cache[requirable] = false
|
156
155
|
end
|
157
156
|
end
|
158
157
|
end
|