leftovers 0.2.3 → 0.3.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 +8 -0
- data/exe/leftovers +1 -1
- data/leftovers.gemspec +5 -2
- data/lib/config/rails.yml +1 -0
- data/lib/config/ruby.yml +8 -5
- data/lib/config/{selenium.yml → selenium-webdriver.yml} +0 -0
- data/lib/leftovers.rb +22 -17
- data/lib/leftovers/argument_rule.rb +29 -19
- data/lib/leftovers/ast/builder.rb +3 -0
- data/lib/leftovers/ast/node.rb +40 -54
- data/lib/leftovers/backports.rb +8 -28
- data/lib/leftovers/cli.rb +16 -10
- data/lib/leftovers/collector.rb +4 -4
- data/lib/leftovers/config.rb +38 -11
- data/lib/leftovers/core_ext.rb +7 -5
- data/lib/leftovers/definition.rb +7 -7
- data/lib/leftovers/definition_set.rb +0 -4
- data/lib/leftovers/file.rb +1 -1
- data/lib/leftovers/file_collector.rb +13 -16
- data/lib/leftovers/file_list.rb +9 -14
- data/lib/leftovers/haml.rb +9 -12
- data/lib/leftovers/hash_rule.rb +12 -10
- data/lib/leftovers/merged_config.rb +9 -8
- data/lib/leftovers/name_rule.rb +62 -17
- data/lib/leftovers/rake_task.rb +3 -3
- data/lib/leftovers/reporter.rb +1 -1
- data/lib/leftovers/rule.rb +22 -14
- data/lib/leftovers/transform_rule.rb +21 -23
- data/lib/leftovers/value_rule.rb +5 -4
- data/lib/leftovers/version.rb +1 -1
- metadata +49 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07755634c2f0119263912ecb6d90a64d37eea60aca5958f1c5f70555b5f63cb6
|
4
|
+
data.tar.gz: ac46e0dc82c7ed6aa10ca1775ecd1d080a4496fd6cbac942631e065892d8742c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb18eaa912ee5df99a96cb34eb9960e258aeec4e23fb00da879b7ea48cc8e42aaaa27d12dd21beb732e68257690ef2f1a8f71ab27f5402fd47c54768a4f895d4
|
7
|
+
data.tar.gz: d13c59bb909652a4bd0a1b4d46a66fc2faf40625e995dcfea43e60aed2a5fd617d2faf1b02408337837fed630474d0ec5c8c46113013d249648c7271783be74b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# v0.3.0
|
2
|
+
- Add simplecov, fix a handful of bugs it found
|
3
|
+
- update fast_ignore
|
4
|
+
|
5
|
+
# v0.2.4
|
6
|
+
- use the right name for selenium-webdriver gem, so the bundler magic can work
|
7
|
+
- handle yaml syntax errors.
|
8
|
+
|
1
9
|
# v0.2.3
|
2
10
|
- restore ability to handle syntax errors. I really need to add coverage to this project
|
3
11
|
- Fix bug with delete_after on an empty string
|
data/exe/leftovers
CHANGED
data/leftovers.gemspec
CHANGED
@@ -35,12 +35,15 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_development_dependency 'pry', '~> 0.1'
|
36
36
|
spec.add_development_dependency 'rake', '>= 13'
|
37
37
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
38
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
38
|
+
spec.add_development_dependency 'rubocop', '~> 0.82'
|
39
39
|
spec.add_development_dependency 'rubocop-performance', '~> 1.4'
|
40
40
|
spec.add_development_dependency 'rubocop-rspec', '~> 1.35'
|
41
|
+
spec.add_development_dependency 'simplecov', '>= 0.18.5'
|
42
|
+
spec.add_development_dependency 'simplecov-console'
|
43
|
+
spec.add_development_dependency 'tty_string', '>= 0.2.1'
|
41
44
|
|
42
45
|
spec.add_development_dependency 'spellr', '>= 0.8.1'
|
43
|
-
spec.add_dependency 'fast_ignore', '>= 0.
|
46
|
+
spec.add_dependency 'fast_ignore', '>= 0.11.0'
|
44
47
|
spec.add_dependency 'parallel'
|
45
48
|
spec.add_dependency 'parser'
|
46
49
|
end
|
data/lib/config/rails.yml
CHANGED
data/lib/config/ruby.yml
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
---
|
2
2
|
include_paths:
|
3
|
-
- '
|
4
|
-
- Gemfile
|
5
|
-
- '*.erb'
|
3
|
+
- '#!:ruby'
|
6
4
|
- '*.gemspec'
|
7
5
|
- .irbrc
|
8
6
|
- irb.rc
|
9
7
|
- _irbrc
|
10
8
|
- $irbrc
|
9
|
+
- Gemfile
|
10
|
+
- '*.erb'
|
11
|
+
- '*.rb'
|
11
12
|
|
12
13
|
test_paths:
|
13
14
|
- /tests/
|
@@ -61,7 +62,8 @@ rules:
|
|
61
62
|
- name: attr_writer
|
62
63
|
defines:
|
63
64
|
argument: '*'
|
64
|
-
|
65
|
+
transforms:
|
66
|
+
- add_suffix: '='
|
65
67
|
- name: attr_accessor
|
66
68
|
defines:
|
67
69
|
- argument: '*'
|
@@ -70,7 +72,8 @@ rules:
|
|
70
72
|
- add_suffix: '='
|
71
73
|
calls:
|
72
74
|
argument: '*'
|
73
|
-
|
75
|
+
transforms:
|
76
|
+
add_prefix: '@'
|
74
77
|
- name: define_method
|
75
78
|
defines:
|
76
79
|
argument: 1
|
File without changes
|
data/lib/leftovers.rb
CHANGED
@@ -7,15 +7,15 @@ require_relative './leftovers/merged_config'
|
|
7
7
|
require_relative './leftovers/reporter'
|
8
8
|
|
9
9
|
module Leftovers # rubocop:disable Metrics/ModuleLength
|
10
|
+
class Error < StandardError; end
|
11
|
+
class ConfigError < Error; end
|
12
|
+
|
10
13
|
module_function
|
11
14
|
|
12
15
|
class << self
|
13
16
|
attr_accessor :parallel
|
14
17
|
alias_method :parallel?, :parallel
|
15
18
|
|
16
|
-
attr_accessor :quiet
|
17
|
-
alias_method :quiet?, :quiet
|
18
|
-
|
19
19
|
attr_accessor :progress
|
20
20
|
alias_method :progress?, :progress
|
21
21
|
end
|
@@ -50,7 +50,6 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def run(stdout: StringIO.new, stderr: StringIO.new) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
53
|
-
reset
|
54
53
|
@stdout = stdout
|
55
54
|
@stderr = stderr
|
56
55
|
return 0 if leftovers.empty?
|
@@ -87,20 +86,19 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
|
|
87
86
|
remove_instance_variable(:@stdout) if defined?(@stdout)
|
88
87
|
remove_instance_variable(:@stderr) if defined?(@stderr)
|
89
88
|
remove_instance_variable(:@parallel) if defined?(@parallel)
|
90
|
-
remove_instance_variable(:@quiet) if defined?(@quiet)
|
91
89
|
remove_instance_variable(:@pwd) if defined?(@pwd)
|
92
90
|
end
|
93
91
|
|
94
92
|
def warn(message)
|
95
|
-
stderr.puts("\e[2K#{message}")
|
93
|
+
stderr.puts("\e[2K#{message}")
|
96
94
|
end
|
97
95
|
|
98
96
|
def puts(message)
|
99
|
-
stdout.puts("\e[2K#{message}")
|
97
|
+
stdout.puts("\e[2K#{message}")
|
100
98
|
end
|
101
99
|
|
102
100
|
def print(message)
|
103
|
-
stdout.print(message)
|
101
|
+
stdout.print(message)
|
104
102
|
end
|
105
103
|
|
106
104
|
def newline
|
@@ -111,18 +109,25 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
|
|
111
109
|
@pwd ||= Pathname.new(Dir.pwd + '/')
|
112
110
|
end
|
113
111
|
|
114
|
-
def
|
112
|
+
def exit(status = 0)
|
113
|
+
throw :leftovers_exit, status
|
114
|
+
end
|
115
|
+
|
116
|
+
def try_require(requirable, message: nil) # rubocop:disable Metrics/MethodLength
|
115
117
|
@try_require ||= {}
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
@try_require[requirable] = false
|
118
|
+
|
119
|
+
@try_require[requirable] = begin
|
120
|
+
if @try_require.key?(requirable)
|
121
|
+
@try_require[requirable]
|
122
|
+
else
|
123
|
+
require requirable
|
124
|
+
true
|
124
125
|
end
|
126
|
+
rescue LoadError
|
127
|
+
false
|
125
128
|
end
|
129
|
+
warn message if !@try_require[requirable] && message
|
130
|
+
@try_require[requirable]
|
126
131
|
end
|
127
132
|
|
128
133
|
def each_or_self(value, &block)
|
@@ -37,7 +37,7 @@ module Leftovers
|
|
37
37
|
@itself = itself
|
38
38
|
|
39
39
|
unless @positions || @keywords || @all_positions || @all_keywords || @key || @itself
|
40
|
-
raise
|
40
|
+
raise Leftovers::ConfigError, "require at least one of 'argument(s)', 'key(s)', itself"
|
41
41
|
end
|
42
42
|
|
43
43
|
@if = prepare_condition(options.delete(:if))
|
@@ -48,7 +48,7 @@ module Leftovers
|
|
48
48
|
|
49
49
|
def prepare_transform(options, transforms, linked_transforms) # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
50
50
|
if linked_transforms && transforms
|
51
|
-
raise
|
51
|
+
raise Leftovers::ConfigError, 'Only use one of linked_transforms/transforms'
|
52
52
|
end
|
53
53
|
return if !linked_transforms && !transforms && options.empty?
|
54
54
|
|
@@ -57,7 +57,7 @@ module Leftovers
|
|
57
57
|
else
|
58
58
|
@linked = !!linked_transforms
|
59
59
|
|
60
|
-
transforms = (linked_transforms || transforms).map do |transform|
|
60
|
+
transforms = Leftovers.array_wrap(linked_transforms || transforms).map do |transform|
|
61
61
|
transform = { transform.to_sym => true } if transform.is_a?(String)
|
62
62
|
Leftovers::TransformRule.new(options.merge(transform))
|
63
63
|
end
|
@@ -70,20 +70,26 @@ module Leftovers
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
def prepare_condition(conditions)
|
73
|
+
def prepare_condition(conditions) # rubocop:disable Metrics/MethodLength
|
74
74
|
Leftovers.array_wrap(conditions).each do |cond|
|
75
|
-
cond
|
75
|
+
unless cond.is_a?(Hash) && cond.keys == [:has_argument]
|
76
|
+
raise Leftovers::ConfigError, <<~MESSAGE
|
77
|
+
Invalid condition #{cond.inspect}. Valid condition keys are: has_argument
|
78
|
+
MESSAGE
|
79
|
+
end
|
80
|
+
|
81
|
+
cond[:has_argument] = HashRule.new(cond[:has_argument])
|
76
82
|
end
|
77
83
|
end
|
78
84
|
|
79
85
|
def prepare_key(key, keys)
|
80
|
-
raise
|
86
|
+
raise Leftovers::ConfigError, 'Only use one of key/keys' if key && keys
|
81
87
|
|
82
88
|
key || keys
|
83
89
|
end
|
84
90
|
|
85
91
|
def prepare_argument(argument, arguments) # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
86
|
-
raise
|
92
|
+
raise Leftovers::ConfigError, 'Only use one of argument/arguments' if argument && arguments
|
87
93
|
|
88
94
|
positions = Set.new
|
89
95
|
keywords = []
|
@@ -98,11 +104,15 @@ module Leftovers
|
|
98
104
|
positions << arg - 1
|
99
105
|
when String, Symbol, Hash
|
100
106
|
keywords << arg
|
107
|
+
else
|
108
|
+
raise Leftovers::ConfigError, <<~MESSAGE
|
109
|
+
Invalid value for argument: #{arg.inspect}. Must by a string ('*', '**', or a keyword), or a hash with the name match rules, or an integer, or an array of these
|
110
|
+
MESSAGE
|
101
111
|
end
|
102
112
|
end
|
103
113
|
|
104
114
|
@positions = positions unless @all_positions || positions.empty? || @all_positions
|
105
|
-
@keywords = NameRule.
|
115
|
+
@keywords = NameRule.wrap(keywords) unless @all_keywords || keywords.empty?
|
106
116
|
end
|
107
117
|
|
108
118
|
def matches(method_node) # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
@@ -135,13 +145,12 @@ module Leftovers
|
|
135
145
|
@unless.all? { |c| !condition_match?(c, method_node) }
|
136
146
|
end
|
137
147
|
|
138
|
-
def condition_match?(condition,
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
hash_node.each_pair.any? { |key, value| condition[:has_argument].match_pair?(key, value) }
|
148
|
+
def condition_match?(condition, method_node)
|
149
|
+
method_node.positional_arguments.each.with_index(1).any? do |value, index|
|
150
|
+
condition[:has_argument].match_pair?(index, value)
|
151
|
+
end || method_node.kwargs&.each_pair&.any? do |key, value|
|
152
|
+
condition[:has_argument].match_pair?(key.to_sym, value)
|
153
|
+
end
|
145
154
|
end
|
146
155
|
|
147
156
|
def hash_values(hash_node, method_node) # rubocop:disable Metrics/MethodLength
|
@@ -160,8 +169,6 @@ module Leftovers
|
|
160
169
|
end
|
161
170
|
|
162
171
|
def value(value_node, method_node) # rubocop:disable Metrics/MethodLength
|
163
|
-
return unless value_node
|
164
|
-
|
165
172
|
value_node = value_node.unwrap_freeze
|
166
173
|
|
167
174
|
case value_node.type
|
@@ -208,12 +215,15 @@ module Leftovers
|
|
208
215
|
end
|
209
216
|
end
|
210
217
|
|
211
|
-
def assert_valid_keys(options, keys)
|
218
|
+
def assert_valid_keys(options, keys) # rubocop:disable Metrics/MethodLength
|
212
219
|
invalid = options.keys - keys
|
213
220
|
|
214
221
|
return if invalid.empty?
|
215
222
|
|
216
|
-
raise
|
223
|
+
raise(
|
224
|
+
Leftovers::ConfigError,
|
225
|
+
"unknown keyword#{'s' if invalid.length > 1}: #{invalid.join(', ')}"
|
226
|
+
)
|
217
227
|
end
|
218
228
|
end
|
219
229
|
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'node'
|
4
|
+
|
3
5
|
module Leftovers
|
4
6
|
module AST
|
5
7
|
class Builder < ::Parser::Builders::Default
|
6
8
|
# Generates {Node} from the given information.
|
7
9
|
#
|
8
10
|
# @return [Node] the generated node
|
11
|
+
|
9
12
|
def n(type, children, source_map)
|
10
13
|
Leftovers::AST::Node.new(type, children, location: source_map)
|
11
14
|
end
|
data/lib/leftovers/ast/node.rb
CHANGED
@@ -5,6 +5,10 @@ require 'parser'
|
|
5
5
|
module Leftovers
|
6
6
|
module AST
|
7
7
|
class Node < Parser::AST::Node # rubocop:disable Metrics/ClassLength
|
8
|
+
# :nocov:
|
9
|
+
using ::Leftovers::SetCaseEq if defined?(::Leftovers::SetCaseEq)
|
10
|
+
# :nocov:
|
11
|
+
|
8
12
|
def initialize(type, children = [], properties = {})
|
9
13
|
# ::AST::Node#initialize freezes itself.
|
10
14
|
# so can't use normal memoizations
|
@@ -17,6 +21,7 @@ module Leftovers
|
|
17
21
|
children.first
|
18
22
|
end
|
19
23
|
|
24
|
+
# TODO: move file to loc.
|
20
25
|
def file
|
21
26
|
@memo[:file]
|
22
27
|
end
|
@@ -35,62 +40,51 @@ module Leftovers
|
|
35
40
|
end
|
36
41
|
|
37
42
|
def to_scalar_value # rubocop:disable Metrics/MethodLength
|
38
|
-
|
39
|
-
when :sym
|
43
|
+
case type
|
44
|
+
when :sym, :int, :float, :str
|
40
45
|
first
|
41
|
-
when :str
|
42
|
-
first.to_s.freeze
|
43
46
|
when :true
|
44
47
|
true
|
45
48
|
when :false
|
46
49
|
false
|
47
50
|
when :nil
|
48
51
|
nil
|
49
|
-
else
|
50
|
-
raise "Not scalar node, (#{type})"
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
def scalar?
|
56
|
+
case type
|
57
|
+
when :sym, :int, :float, :str, :true, :false, :nil
|
58
|
+
true
|
59
|
+
else false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_s
|
64
|
+
@memo[:to_s] ||= name&.to_s || to_scalar_value.to_s || ''
|
62
65
|
end
|
63
66
|
|
64
67
|
def to_sym
|
65
68
|
case type
|
66
|
-
when :
|
69
|
+
when :sym then first
|
67
70
|
when :nil, :true, :false then type
|
68
71
|
else to_s.to_sym
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
|
-
SCALAR_TYPES = %i{sym str true false nil}.freeze
|
73
|
-
def scalar?
|
74
|
-
SCALAR_TYPES.include?(type)
|
75
|
-
end
|
76
|
-
|
77
75
|
def string_or_symbol?
|
78
76
|
type == :str || type == :sym
|
79
77
|
end
|
80
78
|
|
81
|
-
def
|
82
|
-
type == :send || type == :csend
|
83
|
-
end
|
84
|
-
|
85
|
-
def named?
|
86
|
-
send? || type == :casgn
|
87
|
-
end
|
88
|
-
|
89
|
-
def arguments
|
79
|
+
def arguments # rubocop:disable Metrics/MethodLength
|
90
80
|
@memo[:arguments] ||= case type
|
91
81
|
when :send, :csend then children.drop(2)
|
92
82
|
when :casgn then [children[2]]
|
93
|
-
|
83
|
+
when :ivasgn, :cvasgn, :gvasgn then [children[1]]
|
84
|
+
else
|
85
|
+
# :nocov: # these are all the nodes with collect_rules
|
86
|
+
raise "Not argument node (#{type})"
|
87
|
+
# :nocov:
|
94
88
|
end
|
95
89
|
end
|
96
90
|
|
@@ -115,25 +109,18 @@ module Leftovers
|
|
115
109
|
each_pair.map { |k, _| k }
|
116
110
|
end
|
117
111
|
|
118
|
-
def key?(key)
|
119
|
-
each_pair.find do |k, _v|
|
120
|
-
next unless k.string_or_symbol?
|
121
|
-
|
122
|
-
k.to_sym == key
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
112
|
def values
|
113
|
+
# :nocov:
|
127
114
|
@memo[:kwargs] ||= case type
|
115
|
+
# :nocov:
|
128
116
|
when :hash then each_pair.map { |_, v| v }
|
129
117
|
when :array then children
|
130
|
-
else []
|
131
118
|
end
|
132
119
|
end
|
133
120
|
|
134
121
|
def values_at_match(matcher)
|
135
122
|
each_pair.with_object([]) do |(key, value), values|
|
136
|
-
values << value if matcher
|
123
|
+
values << value if matcher === key.to_sym
|
137
124
|
end
|
138
125
|
end
|
139
126
|
|
@@ -142,8 +129,6 @@ module Leftovers
|
|
142
129
|
end
|
143
130
|
|
144
131
|
def each_pair
|
145
|
-
raise "not hash node (#{type})" unless type == :hash
|
146
|
-
|
147
132
|
return enum_for(:each_pair) unless block_given?
|
148
133
|
|
149
134
|
children.each do |pair|
|
@@ -151,22 +136,23 @@ module Leftovers
|
|
151
136
|
end
|
152
137
|
end
|
153
138
|
|
154
|
-
def name
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
139
|
+
def name # rubocop:disable Metrics/MethodLength
|
140
|
+
@memo[:name] ||= case type
|
141
|
+
when :send, :csend, :casgn, :const
|
142
|
+
children[1]
|
143
|
+
when :def, :ivasgn, :ivar, :gvar, :cvar, :gvasgn, :cvasgn
|
144
|
+
first
|
145
|
+
when :module, :class
|
146
|
+
first.name
|
147
|
+
end
|
162
148
|
end
|
163
149
|
|
164
150
|
def [](index) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
151
|
+
# :nocov:
|
165
152
|
case type
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
children[index]
|
153
|
+
# :nocov:
|
154
|
+
when :send, :csend, :casgn, :cvasgn, :ivasgn, :gvasgn
|
155
|
+
index.is_a?(Integer) ? arguments[index - 1] : kwargs && kwargs[index]
|
170
156
|
when :hash
|
171
157
|
each_pair do |key, value|
|
172
158
|
next unless key.string_or_symbol?
|