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 +4 -4
- data/CHANGELOG.md +7 -0
- data/leftovers.gemspec +13 -9
- data/lib/config/ruby.yml +4 -0
- data/lib/leftovers/argument_rule.rb +9 -7
- data/lib/leftovers/ast/builder.rb +19 -0
- data/lib/leftovers/{node.rb → ast/node.rb} +2 -2
- data/lib/leftovers/core_ext.rb +1 -20
- data/lib/leftovers/file_collector.rb +28 -2
- data/lib/leftovers/hash_rule.rb +1 -1
- data/lib/leftovers/name_rule.rb +1 -1
- data/lib/leftovers/value_rule.rb +1 -1
- data/lib/leftovers/version.rb +1 -1
- data/lib/leftovers.rb +17 -1
- metadata +29 -28
- data/.gitignore +0 -4
- data/.leftovers.yml +0 -19
- data/.rspec +0 -3
- data/.rubocop.yml +0 -216
- data/.ruby-version +0 -1
- data/.spellr.yml +0 -13
- data/.spellr_wordlists/english.txt +0 -21
- data/.spellr_wordlists/lorem.txt +0 -1
- data/.spellr_wordlists/ruby.txt +0 -67
- data/.spellr_wordlists/shell.txt +0 -3
- data/.travis.yml +0 -10
- data/Configuration.md +0 -427
- data/Rakefile +0 -16
- data/bin/console +0 -15
- data/bin/setup +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b87286f8934cc673a0c9ccea260ac5bee0117230cf21917d244eb6988b70aede
|
4
|
+
data.tar.gz: c2daf36aaec3ffe393e4adab37bc80ba8bb5a5ffed2f1c94977a3138bbecde05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aca4a439cdbf92fbf6589bf2b9459d209e8ea3affd75bf432648110b58845870f06f80b9815bd1a5404e995a1f4a576885291cffbd1390d45c38f3ff658b9185
|
7
|
+
data.tar.gz: 464a65edd31f10324be77be82b5d28c3632b7b0f691e6268903d9b00190bed3e7c553f6301760c9222dceda12d62e4dba7e927d7dd717300b6effac3e57c790c
|
data/CHANGELOG.md
ADDED
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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-
|
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.
|
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
|
-
|
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
|
-
|
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
|
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.
|
114
|
+
result.leftovers_append values(method_node.positional_arguments, method_node)
|
115
115
|
elsif @positions
|
116
|
-
result.
|
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.
|
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
|
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
|
data/lib/leftovers/core_ext.rb
CHANGED
@@ -3,30 +3,11 @@
|
|
3
3
|
require 'set'
|
4
4
|
|
5
5
|
class Array
|
6
|
-
|
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 '
|
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 =
|
63
|
+
ast, comments = parse_with_comments(@ruby, @file)
|
38
64
|
process_comments(comments)
|
39
65
|
process(ast)
|
40
66
|
rescue Parser::SyntaxError => e
|
data/lib/leftovers/hash_rule.rb
CHANGED
@@ -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
|
-
|
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]),
|
data/lib/leftovers/name_rule.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/leftovers/value_rule.rb
CHANGED
data/lib/leftovers/version.rb
CHANGED
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.
|
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: '
|
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: '
|
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.
|
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.
|
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
|
-
-
|
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
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
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
data/.spellr_wordlists/lorem.txt
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
baz
|
data/.spellr_wordlists/ruby.txt
DELETED
@@ -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
|
data/.spellr_wordlists/shell.txt
DELETED
data/.travis.yml
DELETED
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__)
|