leftovers 0.2.3 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52698685d049f76cfbe3034d85b9de65aec3c06b44434119a6581b399778a648
4
- data.tar.gz: daa5a40d80c7a180eb81a4dd59bc841788da04db541cfc93f2ae02577b1fd251
3
+ metadata.gz: 07755634c2f0119263912ecb6d90a64d37eea60aca5958f1c5f70555b5f63cb6
4
+ data.tar.gz: ac46e0dc82c7ed6aa10ca1775ecd1d080a4496fd6cbac942631e065892d8742c
5
5
  SHA512:
6
- metadata.gz: 98ab99b3d471cdf3d42cf2c2e4940fc985313d68ce6a1ffe7b2f2909b0bcd95c1019a5fccdb306177a8283c0837baf068942a9f390fc38ccdeed9f5ecf8019f7
7
- data.tar.gz: 1dcea67041a8afec49b80ff6b168d18fa28fcba7c6bbd546d0f004f76152f12116d9538cc0920e32721228a8a41233ad8788678d77fd55279f79b000e744ac55
6
+ metadata.gz: eb18eaa912ee5df99a96cb34eb9960e258aeec4e23fb00da879b7ea48cc8e42aaaa27d12dd21beb732e68257690ef2f1a8f71ab27f5402fd47c54768a4f895d4
7
+ data.tar.gz: d13c59bb909652a4bd0a1b4d46a66fc2faf40625e995dcfea43e60aed2a5fd617d2faf1b02408337837fed630474d0ec5c8c46113013d249648c7271783be74b
@@ -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
@@ -3,4 +3,4 @@
3
3
 
4
4
  require_relative '../lib/leftovers/cli'
5
5
 
6
- Leftovers::CLI.new(argv: ARGV)
6
+ exit Leftovers::CLI.new(argv: ARGV).run
@@ -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.74'
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.10.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
@@ -82,6 +82,7 @@ rules:
82
82
  - arguments:
83
83
  - '*'
84
84
  - 'in'
85
+ - within
85
86
  - inclusion
86
87
  - scope
87
88
  - if
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  include_paths:
3
- - '*.rb'
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
- add_suffix: '='
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
- add_prefix: '@'
75
+ transforms:
76
+ add_prefix: '@'
74
77
  - name: define_method
75
78
  defines:
76
79
  argument: 1
@@ -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}") unless quiet?
93
+ stderr.puts("\e[2K#{message}")
96
94
  end
97
95
 
98
96
  def puts(message)
99
- stdout.puts("\e[2K#{message}") unless quiet?
97
+ stdout.puts("\e[2K#{message}")
100
98
  end
101
99
 
102
100
  def print(message)
103
- stdout.print(message) unless quiet?
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 try_require(*requirables, message: nil) # rubocop:disable Metrics/MethodLength
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
- requirables.each do |requirable|
117
- begin
118
- return @try_require[requirable] if @try_require.key?(requirable)
119
-
120
- @try_require[requirable] = require requirable
121
- rescue LoadError
122
- warn message if message
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 ArgumentError, "require at least one of 'argument(s)', 'key(s)', itself"
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 ArgumentError, 'Only use one of linked_transforms/transforms'
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[:has_argument] = HashRule.new(cond[:has_argument]) if cond[:has_argument]
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 ArgumentError, 'Only use one of key/keys' if key && keys
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 ArgumentError, 'Only use one of argument/arguments' if argument && arguments
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.new(keywords) unless @all_keywords || keywords.empty?
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, method_name)
139
- return unless condition[:has_argument]
140
-
141
- hash_node = method_name.kwargs
142
- return false unless hash_node
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 ArgumentError, "unknown keyword#{'s' if invalid.length > 1}: #{invalid.join(', ')}"
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
@@ -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
- @memo[:scalar_value] ||= case type
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 to_s # rubocop:disable Metrics/MethodLength
55
- @memo[:to_s] ||= if scalar?
56
- to_scalar_value
57
- elsif named?
58
- name
59
- else
60
- raise "No to_s, (#{type})"
61
- end.to_s.freeze
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 :str, :sym then first
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 send?
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
- else raise "Not argument node (#{type})"
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.match?(key.to_sym, key.to_s)
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
- return "Not named node (#{type})" unless named?
156
-
157
- @memo[:name] ||= children[1]
158
- end
159
-
160
- def name_s
161
- @memo[:name_s] ||= name.to_s.freeze
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
- when :send, :csend
167
- index.is_a?(Integer) ? arguments[index] : kwargs && kwargs[index]
168
- when :array
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?