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 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?