leftovers 0.1.0 → 0.2.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: 392cec9799ddf44fd1b532c714e70bdeb5bcd56d68843015fd45ab12aa747813
4
- data.tar.gz: 2b34e3689fa2a376e83372234b936f0f9d0a4f0db1bd01f3cd4f48191f8d4f49
3
+ metadata.gz: b87286f8934cc673a0c9ccea260ac5bee0117230cf21917d244eb6988b70aede
4
+ data.tar.gz: c2daf36aaec3ffe393e4adab37bc80ba8bb5a5ffed2f1c94977a3138bbecde05
5
5
  SHA512:
6
- metadata.gz: a8a681a625180b33210f36f74f2d5a2da5ade1955adbf357f9feefdd03fb32ea7088a57392056d4c31d6e937f4dbde79e54547ee80323ae8dd5d16997accea49
7
- data.tar.gz: 1679d83c75a635bf12b2978bb415ae2d5f7280b5a162df16529058af2d3b0b814762e8710704cca3f84aa75e7d4809d396ee1baaa094a618544365fe47e21f77
6
+ metadata.gz: aca4a439cdbf92fbf6589bf2b9459d209e8ea3affd75bf432648110b58845870f06f80b9815bd1a5404e995a1f4a576885291cffbd1390d45c38f3ff658b9185
7
+ data.tar.gz: 464a65edd31f10324be77be82b5d28c3632b7b0f691e6268903d9b00190bed3e7c553f6301760c9222dceda12d62e4dba7e927d7dd717300b6effac3e57c790c
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # v0.2.0
2
+
3
+ Play nice with rubocop
4
+
5
+ # v0.1.0
6
+
7
+ Initial release
data/leftovers.gemspec CHANGED
@@ -16,13 +16,15 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.metadata['homepage_uri'] = spec.homepage
18
18
  spec.metadata['source_code_uri'] = 'http://github.com/robotdana/leftovers'
19
- spec.metadata['changelog_uri'] = 'http://github.com/robotdana/leftovers/blob/master/CHANGELOG'
19
+ spec.metadata['changelog_uri'] = 'http://github.com/robotdana/leftovers/blob/master/CHANGELOG.md'
20
20
 
21
- # Specify which files should be added to the gem when it is released.
22
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(::File.expand_path(__dir__)) do
24
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
- end
21
+ spec.files = Dir.glob('{lib,exe}/**/{*,.*}') + %w{
22
+ CHANGELOG.md
23
+ Gemfile
24
+ LICENSE.txt
25
+ README.md
26
+ leftovers.gemspec
27
+ }
26
28
  spec.bindir = 'exe'
27
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| ::File.basename(f) }
28
30
  spec.require_paths = ['lib']
@@ -33,10 +35,12 @@ Gem::Specification.new do |spec|
33
35
  spec.add_development_dependency 'pry', '~> 0.1'
34
36
  spec.add_development_dependency 'rake', '~> 10.0'
35
37
  spec.add_development_dependency 'rspec', '~> 3.0'
36
- spec.add_development_dependency 'rubocop'
37
- spec.add_development_dependency 'rubocop-rspec'
38
+ spec.add_development_dependency 'rubocop', '~> 0.74'
39
+ spec.add_development_dependency 'rubocop-performance', '~> 1.4'
40
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.35'
41
+
38
42
  spec.add_development_dependency 'spellr', '>= 0.8.1'
39
- spec.add_dependency 'fast_ignore', '>= 0.8.3'
43
+ spec.add_dependency 'fast_ignore', '>= 0.9.0'
40
44
  spec.add_dependency 'parallel'
41
45
  spec.add_dependency 'parser'
42
46
  end
data/lib/config/ruby.yml CHANGED
@@ -29,6 +29,10 @@ rules:
29
29
  - marshal_load # called by Marshal.load
30
30
  - _dump # called by Marshal.dump
31
31
  - _load # called by Marshal.load
32
+ - inherited # called by Subclass < Klass or Class.new(Klass)
33
+ - extended # called by extend Module
34
+ - included # called by include Module
35
+ - $VERBOSE # called by whatever is outputting warnings i guess
32
36
  - name:
33
37
  - send
34
38
  - public_send
@@ -71,7 +71,7 @@ module Leftovers
71
71
  end
72
72
 
73
73
  def prepare_condition(conditions)
74
- Array.wrap(conditions).each do |cond|
74
+ Leftovers.array_wrap(conditions).each do |cond|
75
75
  cond[:has_argument] = HashRule.new(cond[:has_argument]) if cond[:has_argument]
76
76
  end
77
77
  end
@@ -88,7 +88,7 @@ module Leftovers
88
88
  positions = Set.new
89
89
  keywords = []
90
90
 
91
- Array.each_or_self(argument || arguments) do |arg|
91
+ Leftovers.each_or_self(argument || arguments) do |arg|
92
92
  case arg
93
93
  when '*'
94
94
  @all_positions = true
@@ -105,19 +105,21 @@ module Leftovers
105
105
  @keywords = NameRule.new(keywords) unless @all_keywords || keywords.empty?
106
106
  end
107
107
 
108
- def matches(method_node) # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
109
- return Array::EMPTY unless all_conditions_match?(method_node)
108
+ def matches(method_node) # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize
109
+ return [].freeze unless all_conditions_match?(method_node)
110
110
 
111
111
  result = []
112
112
 
113
113
  if @all_positions
114
- result.gather values(method_node.positional_arguments, method_node)
114
+ result.leftovers_append values(method_node.positional_arguments, method_node)
115
115
  elsif @positions
116
- result.gather values(method_node.positional_arguments_at(@positions).compact, method_node)
116
+ result.leftovers_append(
117
+ values(method_node.positional_arguments_at(@positions).compact, method_node)
118
+ )
117
119
  end
118
120
 
119
121
  if @keywords || @all_keywords || @key
120
- result.gather hash_values(method_node.kwargs, method_node)
122
+ result.leftovers_append hash_values(method_node.kwargs, method_node)
121
123
  end
122
124
  result << method_value(method_node) if @itself
123
125
 
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ module AST
5
+ class Builder < ::Parser::Builders::Default
6
+ # Generates {Node} from the given information.
7
+ #
8
+ # @return [Node] the generated node
9
+ def n(type, children, source_map)
10
+ Leftovers::AST::Node.new(type, children, location: source_map)
11
+ end
12
+
13
+ # Don't complain about invalid strings
14
+ def string_value(token)
15
+ value(token)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,9 +2,9 @@
2
2
 
3
3
  require 'parser'
4
4
 
5
- module Parser
5
+ module Leftovers
6
6
  module AST
7
- class Node # rubocop:disable Metrics/ClassLength
7
+ class Node < Parser::AST::Node # rubocop:disable Metrics/ClassLength
8
8
  def initialize(type, children = [], properties = {})
9
9
  # ::AST::Node#initialize freezes itself.
10
10
  # so can't use normal memoizations
@@ -3,30 +3,11 @@
3
3
  require 'set'
4
4
 
5
5
  class Array
6
- # concat, # push, # add, #
7
- EMPTY = [].freeze
8
-
9
- def gather(other)
6
+ def leftovers_append(other)
10
7
  case other
11
8
  when Array, Set then concat(other)
12
9
  when nil then self
13
10
  else self.<< other
14
11
  end
15
12
  end
16
-
17
- def self.wrap(value)
18
- case value
19
- when nil then EMPTY
20
- when Array then value
21
- else [value]
22
- end
23
- end
24
-
25
- def self.each_or_self(value, &block)
26
- case value
27
- when nil then nil
28
- when Array then value.each(&block)
29
- else block.call(value)
30
- end
31
- end
32
13
  end
@@ -4,7 +4,8 @@ require 'fast_ignore'
4
4
  require 'set'
5
5
  require 'parser'
6
6
  require 'parser/current'
7
- require_relative 'node'
7
+ require_relative 'ast/builder'
8
+ require_relative 'ast/node'
8
9
  require_relative 'definition'
9
10
 
10
11
  module Leftovers
@@ -33,8 +34,33 @@ module Leftovers
33
34
  }
34
35
  end
35
36
 
37
+ # mostly copied from https://github.com/whitequark/parser/blob/master/lib/parser/base.rb
38
+ # but with our builder
39
+ def self.parser # rubocop:disable Metrics/MethodLength
40
+ p = ::Parser::CurrentRuby.new(Leftovers::AST::Builder.new)
41
+ p.diagnostics.all_errors_are_fatal = true
42
+ p.diagnostics.ignore_warnings = true
43
+
44
+ p.diagnostics.consumer = lambda do |diagnostic|
45
+ warn(diagnostic.render)
46
+ end
47
+
48
+ p
49
+ end
50
+ PARSER = parser
51
+
52
+ # mostly copied from https://github.com/whitequark/parser/blob/master/lib/parser/base.rb
53
+ # but with our parser
54
+ def parse_with_comments(string, file = '(string)', line = 1)
55
+ PARSER.reset
56
+ source_buffer = ::Parser::CurrentRuby.send(
57
+ :setup_source_buffer, file, line, string, PARSER.default_encoding
58
+ )
59
+ PARSER.parse_with_comments(source_buffer)
60
+ end
61
+
36
62
  def collect
37
- ast, comments = Parser::CurrentRuby.parse_with_comments(@ruby)
63
+ ast, comments = parse_with_comments(@ruby, @file)
38
64
  process_comments(comments)
39
65
  process(ast)
40
66
  rescue Parser::SyntaxError => e
@@ -9,7 +9,7 @@ module Leftovers
9
9
  def initialize(patterns) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/PerceivedComplexity
10
10
  keys = []
11
11
  pairs = []
12
- Array.each_or_self(patterns) do |pat|
12
+ Leftovers.each_or_self(patterns) do |pat|
13
13
  if pat.is_a?(Hash) && pat[:value]
14
14
  pairs << [
15
15
  (NameRule.new(pat[:keyword]) if pat[:keyword]),
@@ -8,7 +8,7 @@ module Leftovers
8
8
  def initialize(patterns) # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize
9
9
  regexps = []
10
10
  syms = Set.new
11
- Array.each_or_self(patterns) do |pat|
11
+ Leftovers.each_or_self(patterns) do |pat|
12
12
  case pat
13
13
  when Leftovers::NameRule
14
14
  syms.merge(pat.sym) if pat.sym
@@ -6,7 +6,7 @@ module Leftovers
6
6
  literal_values = Set.new
7
7
  value_types = Set.new
8
8
 
9
- Array.each_or_self(values) do |value|
9
+ Leftovers.each_or_self(values) do |value|
10
10
  case value
11
11
  when Hash
12
12
  raise ArgumentError, "invalid value #{value.inspect}" unless value[:type]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/leftovers.rb CHANGED
@@ -6,7 +6,7 @@ require_relative './leftovers/collector'
6
6
  require_relative './leftovers/merged_config'
7
7
  require_relative './leftovers/reporter'
8
8
 
9
- module Leftovers
9
+ module Leftovers # rubocop:disable Metrics/ModuleLength
10
10
  module_function
11
11
 
12
12
  class << self
@@ -124,4 +124,20 @@ module Leftovers
124
124
  end
125
125
  end
126
126
  end
127
+
128
+ def each_or_self(value, &block)
129
+ case value
130
+ when nil then nil
131
+ when Array then value.each(&block)
132
+ else yield(value)
133
+ end
134
+ end
135
+
136
+ def array_wrap(value)
137
+ case value
138
+ when nil then [].freeze
139
+ when Array then value
140
+ else [value]
141
+ end
142
+ end
127
143
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leftovers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dana Sherson
@@ -98,30 +98,44 @@ dependencies:
98
98
  name: rubocop
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '0.74'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '0.74'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-performance
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.4'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.4'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rubocop-rspec
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
- - - ">="
129
+ - - "~>"
116
130
  - !ruby/object:Gem::Version
117
- version: '0'
131
+ version: '1.35'
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
- - - ">="
136
+ - - "~>"
123
137
  - !ruby/object:Gem::Version
124
- version: '0'
138
+ version: '1.35'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: spellr
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +156,14 @@ dependencies:
142
156
  requirements:
143
157
  - - ">="
144
158
  - !ruby/object:Gem::Version
145
- version: 0.8.3
159
+ version: 0.9.0
146
160
  type: :runtime
147
161
  prerelease: false
148
162
  version_requirements: !ruby/object:Gem::Requirement
149
163
  requirements:
150
164
  - - ">="
151
165
  - !ruby/object:Gem::Version
152
- version: 0.8.3
166
+ version: 0.9.0
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: parallel
155
169
  requirement: !ruby/object:Gem::Requirement
@@ -186,24 +200,10 @@ executables:
186
200
  extensions: []
187
201
  extra_rdoc_files: []
188
202
  files:
189
- - ".gitignore"
190
- - ".leftovers.yml"
191
- - ".rspec"
192
- - ".rubocop.yml"
193
- - ".ruby-version"
194
- - ".spellr.yml"
195
- - ".spellr_wordlists/english.txt"
196
- - ".spellr_wordlists/lorem.txt"
197
- - ".spellr_wordlists/ruby.txt"
198
- - ".spellr_wordlists/shell.txt"
199
- - ".travis.yml"
200
- - Configuration.md
203
+ - CHANGELOG.md
201
204
  - Gemfile
202
205
  - LICENSE.txt
203
206
  - README.md
204
- - Rakefile
205
- - bin/console
206
- - bin/setup
207
207
  - exe/leftovers
208
208
  - leftovers.gemspec
209
209
  - lib/config/attr_encrypted.yml
@@ -230,6 +230,8 @@ files:
230
230
  - lib/config/will_paginate.yml
231
231
  - lib/leftovers.rb
232
232
  - lib/leftovers/argument_rule.rb
233
+ - lib/leftovers/ast/builder.rb
234
+ - lib/leftovers/ast/node.rb
233
235
  - lib/leftovers/backports.rb
234
236
  - lib/leftovers/cli.rb
235
237
  - lib/leftovers/collector.rb
@@ -245,7 +247,6 @@ files:
245
247
  - lib/leftovers/hash_rule.rb
246
248
  - lib/leftovers/merged_config.rb
247
249
  - lib/leftovers/name_rule.rb
248
- - lib/leftovers/node.rb
249
250
  - lib/leftovers/rake_task.rb
250
251
  - lib/leftovers/reporter.rb
251
252
  - lib/leftovers/rule.rb
@@ -258,7 +259,7 @@ licenses:
258
259
  metadata:
259
260
  homepage_uri: http://github.com/robotdana/leftovers
260
261
  source_code_uri: http://github.com/robotdana/leftovers
261
- changelog_uri: http://github.com/robotdana/leftovers/blob/master/CHANGELOG
262
+ changelog_uri: http://github.com/robotdana/leftovers/blob/master/CHANGELOG.md
262
263
  post_install_message:
263
264
  rdoc_options: []
264
265
  require_paths:
data/.gitignore DELETED
@@ -1,4 +0,0 @@
1
- .rspec_status
2
- Gemfile.lock
3
- /pkg/
4
-
data/.leftovers.yml DELETED
@@ -1,19 +0,0 @@
1
- exclude_paths:
2
- - /vendor
3
-
4
- rules:
5
- - skip: true
6
- name:
7
- - add_insert_cmd # called by ::ERB::Compiler
8
- - add_put_cmd # called by ::ERB::Compiler
9
- - Node
10
- - name:
11
- - RUBY_STRING_METHODS
12
- - ACTIVESUPPORT_STRING_METHODS
13
- - CUSTOM_TRANSFORMS
14
- calls:
15
- argument: 1
16
- - name: HASH_VALUE_TRANSFORMS
17
- calls:
18
- argument: 1
19
- add_suffix: _dynamic
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1,216 +0,0 @@
1
- require: rubocop-rspec
2
-
3
- # Reference:
4
- # https://rubocop.readthedocs.io/en/latest/
5
-
6
- # Keep this in alphabetical order.
7
- # Each override should have a comment (even if it's just "default is bad")
8
-
9
- AllCops:
10
- NewCops: enable
11
- Exclude:
12
- - db/schema*
13
- - .bundle/**/*
14
- - tmp/**/*
15
- - vendor/**/*
16
- DisplayCopNames: true
17
- DisplayStyleGuide: true
18
- TargetRubyVersion: 2.4
19
-
20
- # all of our layout customisations are because we prefer indentation to be
21
- # always consistently 2 spaces, for blocks, scopes, multiline expressions, etc
22
- # e.g.
23
- # class Klass
24
- # def method(arg1,
25
- # arg2)
26
- # value = if arg1 == 'value' && arg2 == 'value'
27
- # method2
28
- # .method(arg_a, arg_b,
29
- # arg_c, arg_d, keyword1: true,
30
- # keyword2: true) do
31
- # @last = [
32
- # arg_a, arg_b,
33
- # arg_c, arg_d
34
- # ]
35
- # end
36
- # end
37
- # value
38
- # end
39
- # end
40
-
41
- # to match our preference for consistent indentation
42
- Layout/HashAlignment:
43
- EnforcedLastArgumentHashStyle: always_ignore
44
-
45
- # to match our preference for consistent indentation
46
- Layout/ParameterAlignment:
47
- EnforcedStyle: with_fixed_indentation
48
-
49
- # to match our preference for consistent indentation
50
- Layout/BlockAlignment:
51
- EnforcedStyleAlignWith: start_of_block
52
-
53
- # to match our preference for consistent indentation
54
- Layout/CaseIndentation:
55
- EnforcedStyle: end
56
-
57
- # to match our preference for consistent indentation
58
- Layout/EndAlignment:
59
- EnforcedStyleAlignWith: start_of_line
60
-
61
- # Aligning Assignments, etc makes diffs noisy
62
- Layout/ExtraSpacing:
63
- AllowForAlignment: false
64
-
65
- # to match our preference for consistent indentation
66
- Layout/FirstArrayElementLineBreak:
67
- Enabled: true
68
-
69
- # to match our preference for consistent indentation
70
- Layout/FirstHashElementLineBreak:
71
- Enabled: true
72
-
73
- # to match our preference for consistent indentation
74
- Layout/FirstArgumentIndentation:
75
- EnforcedStyle: consistent
76
-
77
- # to match our preference for consistent indentation
78
- Layout/FirstArrayElementIndentation:
79
- EnforcedStyle: consistent
80
-
81
- # to match our preference for consistent indentation
82
- Layout/FirstHashElementIndentation:
83
- EnforcedStyle: consistent
84
-
85
- # to match our preference for consistent indentation
86
- # and hanging assignment looks lost
87
- Layout/MultilineAssignmentLayout:
88
- EnforcedStyle: same_line
89
-
90
- # this changes our preferred:
91
- # value = if thing1 &&
92
- # thing2
93
- # to:
94
- # value = if thing1 &&
95
- # thing2
96
- # even though the IndentationWidth is 2
97
- # but it's right most of the time so I put up with it
98
- Layout/MultilineOperationIndentation:
99
- EnforcedStyle: indented
100
-
101
- Layout/MultilineMethodCallIndentation:
102
- EnforcedStyle: indented
103
-
104
- # Temporarily disable this spec as a recent change has broken it for us:
105
- # https://github.com/rubocop-hq/rubocop/issues/6254
106
- Layout/RescueEnsureAlignment:
107
- Enabled: false
108
-
109
- Metrics:
110
- CountComments: false
111
-
112
- Metrics/BlockLength:
113
- ExcludedMethods:
114
- - configure
115
- - describe
116
- - context
117
- - it
118
-
119
- Layout/LineLength:
120
- Max: 100
121
- IgnoreCopDirectives: true
122
-
123
- Metrics/MethodLength:
124
- Max: 5
125
-
126
- Naming/MethodParameterName:
127
- AllowedNames: [_, io, id, to, by, 'on', in, at, ip, db]
128
-
129
- RSpec:
130
- Enabled: true
131
- Include:
132
- - spec/**/*.rb
133
-
134
- RSpec/DescribeClass:
135
- Enabled: false
136
-
137
- RSpec/ExampleLength:
138
- Enabled: false
139
-
140
- # I misuse matchers often
141
- RSpec/ExpectActual:
142
- Enabled: false
143
-
144
- RSpec/FilePath:
145
- Enabled: false
146
-
147
- # Multiple expectations are useful
148
- # checking you've partially achieved something on the way to completely achieving it is useful for debugging failures
149
- RSpec/MultipleExpectations:
150
- Enabled: false
151
-
152
- # It should be obvious from context. Chill out rubocop
153
- RSpec/NamedSubject:
154
- Enabled: false
155
-
156
-
157
- # This matches the style we've been using all along (ever so slightly more frequently)
158
- Style/Alias:
159
- EnforcedStyle: prefer_alias_method
160
-
161
- Style/CollectionMethods:
162
- Enabled: true
163
-
164
- # we don't rdoc
165
- Style/Documentation:
166
- Enabled: false
167
-
168
- # [a, b].include?(x) is more unclear than a == x || b == x
169
- Style/MultipleComparison:
170
- Enabled: false
171
-
172
- Style/NumericPredicate:
173
- Enabled: false
174
-
175
- # we use %w{} pretty frequently
176
- Style/PercentLiteralDelimiters:
177
- PreferredDelimiters:
178
- default: '{}'
179
- '%w': '{}'
180
- '%W': '{}'
181
- '%i': '{}'
182
- '%I': '{}'
183
- '%r': '{}'
184
-
185
- # We want this to warn to force consistency within the codebase.
186
- Style/SafeNavigation:
187
- Enabled: true
188
-
189
- # different methods calls that do exactly the same thing are a smell, regardless of semantics
190
- Style/SignalException:
191
- EnforcedStyle: only_raise
192
-
193
- # this wants less descriptive names
194
- Style/SingleLineBlockParams:
195
- Enabled: false
196
-
197
- Style/HashEachMethods:
198
- Enabled: true
199
- Style/HashTransformKeys:
200
- Enabled: true
201
- Style/HashTransformValues:
202
- Enabled: true
203
- Lint/RaiseException:
204
- Enabled: true
205
- Lint/StructNewOverride:
206
- Enabled: true
207
-
208
- # hey rubocop you even use parser which uses :true and :false types. no
209
- Lint/BooleanSymbol:
210
- Enabled: false
211
-
212
- Style/DoubleNegation:
213
- Enabled: false
214
-
215
- RSpec/InstanceVariable:
216
- Enabled: false # I'll figure it out soon
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.5.1
data/.spellr.yml DELETED
@@ -1,13 +0,0 @@
1
- excludes:
2
- - vendor
3
- languages:
4
- english:
5
- locale: [US, AU]
6
- lorem:
7
- includes:
8
- - /spec/
9
- ruby:
10
- includes:
11
- - README.md
12
- - Configuration.md
13
- - '*.yml'
@@ -1,21 +0,0 @@
1
- affixxed
2
- backports
3
- classnames
4
- codebase
5
- esque
6
- gemfile
7
- hashbang
8
- lorem
9
- nocov
10
- noninfringement
11
- precompiled
12
- readme
13
- requirables
14
- rspec
15
- rubo
16
- rvm
17
- sherson
18
- todo
19
- unmemoize
20
- wtf
21
- yml
@@ -1 +0,0 @@
1
- baz
@@ -1,67 +0,0 @@
1
- activesupport
2
- asgn
3
- ast
4
- autolink
5
- bigint
6
- camelcase
7
- camelize
8
- capfile
9
- casgn
10
- cattr
11
- changelog
12
- codespan
13
- configs
14
- coverband
15
- csend
16
- cvasgn
17
- cyclomatic
18
- deconstantize
19
- demodulize
20
- diffable
21
- dstr
22
- dsym
23
- eflipflop
24
- encryptor
25
- gitignore
26
- guardfile
27
- gvasgn
28
- haml
29
- hrule
30
- iflipflop
31
- irange
32
- ivasgn
33
- jbuilder
34
- kwbegin
35
- kwoptarg
36
- kwrestarg
37
- linebreak
38
- lvars
39
- lvasgn
40
- masgn
41
- mattr
42
- memoizations
43
- optarg
44
- postexe
45
- postprocess
46
- precompile
47
- preexe
48
- preload
49
- procarg
50
- pryrc
51
- regexps
52
- resbody
53
- restarg
54
- rhtml
55
- rjs
56
- rspec
57
- rubocop
58
- shadowarg
59
- simplecov
60
- strikethrough
61
- subnodes
62
- syms
63
- titlecase
64
- titleize
65
- usr
66
- vasgn
67
- xstr
@@ -1,3 +0,0 @@
1
- env
2
- euo
3
- usr
data/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.4
6
- - 2.5
7
- - 2.6
8
- - 2.7
9
- before_install: gem install bundler
10
-
data/Configuration.md DELETED
@@ -1,427 +0,0 @@
1
- # Configuration
2
-
3
- The configuration is read from `.leftovers.yml` in your project root.
4
- Its presence is optional and all of these settings are optional:
5
-
6
- see the [built in config files](https://github.com/robotdana/leftovers/tree/master/lib/config) for examples.
7
-
8
- - [`include_paths:`](#include_paths)
9
- - [`exclude_paths:`](#exclude_paths)
10
- - [`test_paths:`](#test_paths)
11
- - [`gems:`](#gems)
12
- - [`rules:`](#rules)
13
- - [`names:`](#names)
14
- - [`has_prefix](#has_prefix-has_suffix)
15
- - [`has_suffix](#has_prefix-has_suffix)
16
- - [`matches](#matches)
17
- - [`paths:`](#paths)
18
- - [`skip:`](#skip)
19
- - [`calls:`](#calls-defines), [`defines:`](#calls-defines)
20
- - [`arguments:`](#arguments), [`keys:`](#keys-), [`itself:`](#itself-true)
21
- - [`transforms:`](#transforms), [`linked_transforms:`](#linked_transforms)
22
- - `original:`, `add_prefix:`, `add_suffix:`, `delete_prefix:`, `delete_suffix:`, `replace_with:`
23
- - `delete_before:`, `delete_after:`, `downcase:`, `upcase:`, `capitalize:`, `swapcase:`
24
- - `pluralize`, `singularize`, `camelize`, `underscore`, `demodulize`, `deconstantize`
25
- - [`if:`](#if-unless), [`unless:`](#if-unless)
26
- - [`has_argument:`](#has_argument)
27
- - `keyword:`
28
- - [`has_prefix:`](#has_prefix-has_suffix)
29
- - [`has_suffix:`](#has_prefix-has_suffix)
30
- - [`matches:`](#matches)
31
- - `value:`
32
- - [`has_prefix:`](#has_prefix-has_suffix)
33
- - [`has_suffix:`](#has_prefix-has_suffix)
34
- - [`matches:`](#matches)
35
- - `type:`
36
-
37
-
38
- ## `include_paths:`
39
-
40
- List filenames/paths in the gitignore format of files to be checked using a [gitignore-esque format](https://github.com/robotdana/fast_ignore#using-an-includes-list).
41
-
42
- ```yml
43
- include_paths:
44
- - '*.rb'
45
- - '*.rake'
46
- - Gemfile
47
- ```
48
-
49
- Also it will check files with no extension that have `ruby` in the shebang/hashbang, e.g. `#!/usr/bin/env ruby` or `#!/usr/bin/ruby` etc
50
-
51
- ## `exclude_paths:`
52
-
53
- List filenames/paths that match the above that you might want to exclude, using the gitignore format.
54
- By default it will also read your project's .gitignore file and ignore anything there.
55
-
56
- ```yml
57
- exclude_paths:
58
- - /some/long/irrelevant/generated/file
59
- ```
60
-
61
- ## `test_paths:`
62
-
63
- list filenames/paths of test directories that will be used to determine if a method/etc is only tested but not otherwise used.
64
- Also in the gitignore format
65
-
66
- ```yml
67
- test_paths:
68
- - /test/
69
- - /spec/
70
- ```
71
-
72
- ## `gems:`
73
-
74
- By default Leftovers will look at your Gemfile.lock file to find all gem dependencies
75
-
76
- If you don't use bundler, or don't have a Gemfile.lock for some reason, you can still take advantage of the built in handling for certain gems
77
- ```yml
78
- gems:
79
- - rspec
80
- - rails
81
- ```
82
-
83
- ## `rules:`
84
-
85
- This is the most complex part of configuration, and is a list of methods that define/call other methods/classes/etc.
86
- Each must have a list of `names:`. and can optionally be limited to a list of `paths:`.
87
-
88
- This rule can either `skip:` these names, or describe method/class `calls:` and definitions (`defines:`).
89
-
90
- ### `names:`
91
- **required**
92
-
93
- _alias `name:`_
94
-
95
- list methods/classnames/etc that this rule applies to.
96
-
97
- ```yml
98
- rules:
99
- - names:
100
- - initialize
101
- - ClassName
102
- skip: true
103
- - name: respond_to_missing?
104
- skip: true
105
- ```
106
-
107
- #### `has_prefix:`, `has_suffix:`
108
-
109
- To match names other than exact strings, you can use has_suffix or has_prefix or both if you're feeling fancy.
110
-
111
- ```yml
112
- rules:
113
- - names:
114
- - has_suffix: Helper # will match Helper, LinkHelper FormHelper, etc
115
- - has_prefix: be_ # will match be_equal, be_invalid, etc
116
- - { has_prefix: is_, has_suffix: '?' } # will match is_invalid?, is_equal? etc
117
- skip: true
118
- ```
119
-
120
-
121
- #### `matches:`
122
-
123
- if `has_suffix:` and `has_prefix:` isn't enough, you can use `matches:` to supply a regexp.
124
- This string is automatically converted into a ruby regexp and must match the whole method/constant name.
125
- ```yml
126
- rules:
127
- - names:
128
- - matches: 'column_\d+' # will match column_1, column_2, column_99, but not column_left etc
129
- skip: true
130
- ```
131
-
132
- ### `paths:`
133
- _alias `path:`_
134
-
135
- An optional list of paths that limits what paths this method rule can apply to, defined using a .gitignore-esque format
136
-
137
- ```yml
138
- rules:
139
- - name:
140
- - has_suffix: Helper
141
- path: /app/helpers
142
- skip: true
143
- ```
144
-
145
- ### `skip:`
146
-
147
- Skip methods that are called on your behalf by code outside your project, or called dynamically using send with variables.
148
-
149
- You can also skip method calls and definitions in place using [magic comments](https://github.com/robotdana/leftovers/tree/master/README.md#magic-comments).
150
-
151
- ```yml
152
- rules:
153
- - name: initialize
154
- skip: true
155
- ```
156
- ```ruby
157
- def initialize
158
- end
159
- ```
160
-
161
- will not report that you didn't directly use the initialize method
162
-
163
- ### `calls:`, `defines:`
164
- _aliases `call:`, `define:`_
165
- Describe implicitly called and defined methods using these keys. they're structured the same way:
166
-
167
- It must have at least one of `argument:`, `itself: true`, or `keys: '*'` which points to the implied method definition/call.
168
- This value must be a literal string, symbol, or array of strings or symbols.
169
-
170
- #### `arguments:`
171
- _alias `argument:`_
172
-
173
- the position or keyword of the value or values being implicitly called/defined.
174
- it can be a single argument or a list.
175
-
176
- This value must be itself a literal String, Symbol, or Array or Hash whose values are Strings and Symbols or more nested Arrays and Hashes.
177
- Variables and other method calls returning values will be ignored.
178
-
179
- `*` means all positional arguments values. `**` means all keyword arguments values.
180
- Positional arguments start at 1.
181
-
182
- ```yml
183
- rules:
184
- # `send(:my_method, arg)` is equivalent to `my_method(arg)`
185
- - name: send
186
- calls:
187
- argument: 1
188
- ```
189
- ```ruby
190
- user.send(:my_private_method, true)
191
- ```
192
- will count as a call to `my_private_method`.
193
-
194
- ```yml
195
- - name: attr_reader
196
- defines:
197
- arguments: '*'
198
- ```
199
- ```ruby
200
- attr_reader :my_attr, :my_other_attr
201
- ```
202
- will count as a definition of `my_attr` and `my_other_attr` and will need to be used elsewhere or they'll be reported as leftovers.
203
-
204
- ```yml
205
- rules:
206
- - name: validate
207
- calls:
208
- - arguments: ['*', if, unless]
209
- ```
210
- ```ruby
211
- validate :does_not_match_existing_record, if: :new_record?
212
- ```
213
- will count as a call to `does_not_match_existing_record`, and `new_record?`
214
-
215
- ##### Constant assignment.
216
-
217
- In addition to method call arguments, this can be used for constant assignment, as often constant assignment plus class_eval/instance_eval/define_method is used to dry up similar methods.
218
- ```yml
219
- rules:
220
- - name: METHOD_NAMES
221
- defines:
222
- - arguments: 1
223
- add_suffix: _attributes
224
- calls:
225
- - arguments: 1
226
- ```
227
- ```ruby
228
- METHOD_NAMES = %w{user account}.freeze
229
- METHOD_NAMES.each do |method_name|
230
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
231
- def #{method}_attributes
232
- self.#{method}
233
- end
234
- end
235
- end
236
- ```
237
- counts as a definition of `user_attributes` and `account_attributes` and calls to `user` and `account`
238
-
239
- use `arguments: '**'`, and or `keys: true` for assigning hashes
240
- ```yml
241
- rules:
242
- - name: METHOD_NAMES
243
- defines:
244
- - keys: '*'
245
- add_prefix: setup_
246
- calls:
247
- - arguments: '**'
248
- add_prefix: build_
249
- ```
250
- ```ruby
251
- METHOD_NAMES = { user: :login, account: :profile }
252
- METHOD_NAMES.each do |method_name|
253
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
254
- def setup_#{method}
255
- build_#{method}
256
- end
257
- end
258
- end
259
- ```
260
- Would count as defining `setup_user`, and `setup_account` and calling `build_login` and `build_profile`
261
-
262
- #### `itself: true`
263
-
264
- Will supply the method/constant name itself as the thing to be transformed.
265
- The original method/constant name will continue to be defined as normal
266
- ```yml
267
- - name:
268
- has_prefix: be_
269
- calls:
270
- itself: true
271
- delete_prefix: be_
272
- add_suffix: '?'
273
- ```
274
- ```ruby
275
- expect(value).to be_empty
276
- ```
277
- will count `be_empty` as a call to `empty?`
278
-
279
- #### `keys: '*'`
280
- When the keyword argument **keywords** are the thing being called.
281
-
282
- ```yml
283
- rules:
284
- - name: validates
285
- calls:
286
- - arguments: '*'
287
- - keys: '*'
288
- add_suffix: Validator
289
- activesupport: camelize
290
- ```
291
- ```ruby
292
- validates :first_name, :surname, presence: true
293
- ```
294
- will count calls for `validates`, `first_name`, `surname`, and `PresenceValidator`
295
-
296
- #### `transforms:`
297
-
298
- Sometimes the method being called is modified from the literal argument, sometimes that's just appending an `=` and sometimes it's more complex:
299
-
300
- ```yml
301
- - name: attribute
302
- defines:
303
- - argument: 1
304
- transforms:
305
- - original # no transformation
306
- - add_suffix: '?'
307
- - add_suffix: '='
308
- ```
309
- ```ruby
310
- attribute :first_name
311
- ```
312
- will count as a definition of `first_name`, `first_name=` and `first_name?`
313
-
314
- If there is just one transform for the arguments you can remove the `transforms:` keyword and move everything up a level.
315
-
316
- ```yml
317
- - name: attr_writer
318
- defines:
319
- - argument: '*'
320
- add_suffix: '='
321
- ```
322
- ```ruby
323
- attr_writer :first_name, :surname
324
- ```
325
- will count as the definition of `first_name=`, and `surname=`
326
-
327
- | transform | examples | effect |
328
- | --- | --- | --- |
329
- |original| `original`, `original: true` | no change. useful when grouped with other transforms |
330
- |add_prefix| `add_prefix: be_`, `add_prefix: { from_argument: 'to', joiner: '_' }` | adds the prefix string. possibly from another attribute (used for rails' delegate). |
331
- |add_suffix| `add_suffix: '?'`, `add_suffix: Validator` | adds the suffix string. possibly from another attribute. |
332
- |delete_prefix| `delete_prefix: be_` | removes the prefix string. |
333
- |delete_suffix| `delete_suffix: _html` | removes the suffix string. |
334
- |delete_before| `delete_before: '#'` | removes everything up to and including the string. used for rails' routes. |
335
- |delete_after| `delete_after: '#'` | removes everything after to and including the string. used for rails' routes. |
336
- |replace_with| `replace_with: html` | replaces the original string, perhaps because it dynamically calls it |
337
- |downcase| `downcase`, `downcase: true` | calls ruby's `String#downcase` |
338
- |upcase| `upcase`, `upcase: true` | calls ruby's `String#upcase` |
339
- |capitalize| `capitalize`, `capitalize: true` | calls ruby's `String#capitalize` |
340
- |swapcase| `swapcase`, `swapcase: true` | calls ruby's `String#swapcase` |
341
- |pluralize| `pluralize`, `pluralize: true` | calls activesupport's `String#pluralize` extension. Will try to load config/initializers/inflections.rb |
342
- |singularize| `singularize`, `singularize: true` | calls activesupport's `String#singularize` extension. Will try to load config/initializers/inflections.rb |
343
- |camelize| `camelize`, `camelize: true`, `camelcase`, `camelcase: true` | calls activesupport's `String#camelize` extension. Will try to load config/initializers/inflections.rb |
344
- |underscore| `underscore`, `underscore: true` | calls activesupport's `String#underscore` extension. |
345
- |demodulize| `demodulize`, `demodulize: true` | calls activesupport's `String#demodulize` extension. |
346
- |deconstantize| `deconstantize`, `deconstantize: true` | calls activesupport's `String#deconstantize` extension. |
347
- |titleize| `titleize`, `titleize: true`, `titlecase`, `titlecase: true` | calls activesupport's `String#titleize` extension. |
348
- |parameterize| `parameterize`, `parameterize: true` | calls activesupport's `String#parameterize` extension. |
349
-
350
- #### `linked_transforms:`
351
-
352
- This is identical to `transforms:` except that a call to one of the defined methods counts as a call to them all.
353
-
354
- ```yml
355
- - name: attribute
356
- defines:
357
- - argument: 1
358
- linked_transforms:
359
- - original # no transformation
360
- - add_suffix: '?'
361
- - add_suffix: '='
362
- ```
363
- ```ruby
364
- attribute :first_name
365
-
366
- def initialize
367
- self.first_name = 'dana'
368
- end
369
- ```
370
- will count as a definition of `first_name`, `first_name=` and `first_name?`, and because of `linked_transforms` the call to `first_name=` also counts as a call to `first_name?` and `first_name`
371
-
372
- #### `if:`, `unless:`
373
-
374
- Sometimes what to do depends on other arguments than the ones looked at:
375
- e.g. rails' `delegate` method has a `prefix:` argument of its own that is used when defining methods:
376
-
377
- `if:` and `unless:` work the same way and can be given a list or single value of conditions. For a list, all conditions must be met.
378
-
379
- ```yml
380
- rules:
381
- - name: field
382
- calls:
383
- - argument: 1
384
- unless:
385
- has_argument: method
386
- - argument: method
387
- ```
388
- ```ruby
389
- field :first_name
390
- field :family_name, method: :surname
391
- ```
392
- would count calls to `first_name`, and `surname`, but not `family_name`
393
-
394
- ##### `has_argument:`
395
-
396
- has_argument can be given a keyword or list of keywords. or a list of patterns like name.
397
- or to check either the exact value or type of value it can be given `keyword:` and `value:` which also match the patterns like `name:`.
398
- instead of an exact value `value:` can be given a type or list of type.
399
-
400
- This all comes together to give the most complex rule, rails delegate method.
401
- ```yml
402
- rules:
403
- - name: delegate
404
- defines:
405
- - argument: '*'
406
- if:
407
- has_argument:
408
- keyword: prefix
409
- value: true # if the value of the prefix keyword argument is literal true value
410
- add_prefix:
411
- from_argument: to # use the value of the "to" keyword as the prefix
412
- joiner: '_' # joining with _ to the original string
413
- - argument: '*'
414
- if: # if the method call has a prefix keyword argument that is not a literal true value
415
- has_argument:
416
- keyword: prefix
417
- value:
418
- type: [String, Symbol]
419
- add_prefix:
420
- from_argument: prefix # use the value of the "prefix" keyword as the prefix
421
- joiner: '_' # joining with _ to the original string
422
- calls:
423
- - argument: to # consider the to argument called.
424
- - argument: '*'
425
- if:
426
- has_argument: prefix # if there is a prefix, consider the original method called.
427
- ```
data/Rakefile DELETED
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'bundler/gem_tasks'
5
- require 'rspec/core/rake_task'
6
- require 'rubocop/rake_task'
7
- require 'spellr/rake_task'
8
- require_relative 'lib/leftovers/rake_task'
9
-
10
- # RuboCop::RakeTask.new
11
- RSpec::Core::RakeTask.new(:spec)
12
- Spellr::RakeTask.generate_task
13
- Leftovers::RakeTask.generate_task(:leftovers, '--no-progress')
14
-
15
- # rubocop is misbehaving currently
16
- task default: %i{spec spellr leftovers}
data/bin/console DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'leftovers'
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require 'irb'
15
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here