leftovers 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/README.md +7 -4
- data/docs/Configuration.md +29 -0
- data/lib/leftovers.rb +1 -0
- data/lib/leftovers/ast/node.rb +4 -4
- data/lib/leftovers/config.rb +4 -0
- data/lib/leftovers/config_validator/schema_hash.rb +7 -6
- data/lib/leftovers/definition.rb +2 -2
- data/lib/leftovers/definition_node.rb +36 -0
- data/lib/leftovers/definition_set.rb +15 -8
- data/lib/leftovers/file_collector.rb +10 -5
- data/lib/leftovers/merged_config.rb +4 -0
- data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -6
- data/lib/leftovers/value_processors/return_definition.rb +5 -3
- data/lib/leftovers/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3fb0707b239e6e7581c2997969483c72b3ff272895173828fc3434c08de165a
|
4
|
+
data.tar.gz: aadfba4e9fc93b110599c8e2bd66f723efbce39cabf4deda036d904358cfa131
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 129fe2d42ec0f47d9f76105c1d53f0209133864d77688db231cb9fbc3c5ad3e6ea3ea8bdd95b1902b480b8a7e78709f2c197b261e1132ae0ce3cddc618e39899
|
7
|
+
data.tar.gz: 1d01550bdf1762344c2744d21f01c1590b928a751439714e5ad364211b2a914aec486415f1d5769113b1d3bf23023319c3d68bf72b733367dc7851fdc9e4ffb9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# v0.4.1
|
2
|
+
- add `test_only:` to mark methods/constants/assignments as test_only in the config rather than just with magic comments
|
1
3
|
|
2
4
|
# v0.4.0
|
3
5
|
- add `requires:` to .leftovers.yml config to e.g. load inflections in a different place than `config/initializers/inflections`
|
data/README.md
CHANGED
@@ -72,16 +72,16 @@ class MyClass
|
|
72
72
|
end
|
73
73
|
```
|
74
74
|
This would report `MyClass` is unused, but not my_method
|
75
|
-
To do this for all definitions of this name, add the name
|
75
|
+
To do this for all definitions of this name, instead of adding a comment, add the name to the [`keep:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#keep) list in the [configuration file](#configuration-file).
|
76
76
|
|
77
|
-
### `# leftovers:
|
77
|
+
### `# leftovers:test_only`
|
78
78
|
_aliases `leftovers:for_test`, `leftovers:for_tests`, `leftovers:test`, `leftovers:tests`, `leftovers:testing`_
|
79
79
|
|
80
|
-
To mark a definition from a non-test dir, as intentionally only used by tests, use `leftovers:
|
80
|
+
To mark a definition from a non-test dir, as intentionally only used by tests, use `leftovers:test_only`
|
81
81
|
```ruby
|
82
82
|
# app/my_class.rb
|
83
83
|
class MyClass
|
84
|
-
def my_method # leftovers:
|
84
|
+
def my_method # leftovers:test_only
|
85
85
|
true
|
86
86
|
end
|
87
87
|
end
|
@@ -95,6 +95,8 @@ end
|
|
95
95
|
|
96
96
|
This would consider `my_method` to be used, even though it is only called by tests.
|
97
97
|
|
98
|
+
To do this for all definitions of this name, instead of adding a comment, add the name to the [`test_only:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#test_only) list in the [configuration file](#configuration-file).
|
99
|
+
|
98
100
|
### `# leftovers:call`
|
99
101
|
_aliases `leftovers:calls`_
|
100
102
|
To mark a dynamic call that doesn't use literal values, use `leftovers:call` with the method name listed
|
@@ -116,6 +118,7 @@ Its presence is optional and all of these settings are optional.
|
|
116
118
|
- [`requires:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#requires)
|
117
119
|
- [`gems:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#gems)
|
118
120
|
- [`keep:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#keep)
|
121
|
+
- [`test_only:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#test_only)
|
119
122
|
- [`dynamic:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#dynamic)
|
120
123
|
|
121
124
|
see the [complete config documentation](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md) for details.
|
data/docs/Configuration.md
CHANGED
@@ -9,6 +9,7 @@ Its presence is optional and all of these settings are optional.
|
|
9
9
|
- [`requires:`](#requires)
|
10
10
|
- [`gems:`](#gems)
|
11
11
|
- [`keep:`](#keep)
|
12
|
+
- [`test_only:](#test_only)
|
12
13
|
- [`dynamic:`](#dynamic)
|
13
14
|
|
14
15
|
see the [built in config files](https://github.com/robotdana/leftovers/tree/main/lib/config) or [this repo's own config](https://github.com/robotdana/leftovers/tree/main/.leftovers.yml) for examples.
|
@@ -120,6 +121,34 @@ keep:
|
|
120
121
|
|
121
122
|
Alternatively, you can mark method/constants/variables in-place using [magic comments](https://github.com/robotdana/leftovers/tree/main/README.md#magic-comments).
|
122
123
|
|
124
|
+
## `test_only:`
|
125
|
+
|
126
|
+
This is a list of methods/constants/variables that are ok to be defined outside of [test paths](#test_paths), but only used within test paths, maybe because they're your public api, or convenience methods for tests etc.
|
127
|
+
|
128
|
+
Each entry can be a string (an exact match for a method, constant, or variable name that includes the sigil), or have at least one of the following properties:
|
129
|
+
- [`names:`](#names)
|
130
|
+
or the properties from `names:`
|
131
|
+
- [`has_prefix:`](#has_prefix)
|
132
|
+
- [`has_suffix:`](#has_suffix)
|
133
|
+
- [`matches:`](#matches) (can't be used in the same entry as `has_prefix:` or `has_suffix:`)
|
134
|
+
- [`paths:`](#paths)
|
135
|
+
- [`has_arguments:`](#has_arguments)
|
136
|
+
- [`unless`](#unless)
|
137
|
+
|
138
|
+
Arrays are not necessary for single values
|
139
|
+
|
140
|
+
example from rails.yml
|
141
|
+
```yml
|
142
|
+
test_only:
|
143
|
+
- APP_PATH
|
144
|
+
- ssl_configured?
|
145
|
+
- has_suffix: Helper
|
146
|
+
path: /app/helpers
|
147
|
+
...
|
148
|
+
```
|
149
|
+
|
150
|
+
Alternatively, you can mark method/constants/variables in-place using [magic comments](https://github.com/robotdana/leftovers/tree/main/README.md#magic-comments).
|
151
|
+
|
123
152
|
## `dynamic:`
|
124
153
|
|
125
154
|
This is a list of methods, constants, or variables whose called arguments or assigned value/s are used to dynamically `call:` or define (`define:`) other methods, constants, or variables
|
data/lib/leftovers.rb
CHANGED
@@ -11,6 +11,7 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
|
|
11
11
|
autoload(:Collector, "#{__dir__}/leftovers/collector")
|
12
12
|
autoload(:ConfigValidator, "#{__dir__}/leftovers/config_validator")
|
13
13
|
autoload(:Config, "#{__dir__}/leftovers/config")
|
14
|
+
autoload(:DefinitionNode, "#{__dir__}/leftovers/definition_node")
|
14
15
|
autoload(:DefinitionSet, "#{__dir__}/leftovers/definition_set")
|
15
16
|
autoload(:Definition, "#{__dir__}/leftovers/definition")
|
16
17
|
autoload(:ERB, "#{__dir__}/leftovers/erb")
|
data/lib/leftovers/ast/node.rb
CHANGED
@@ -25,12 +25,12 @@ module Leftovers
|
|
25
25
|
@memo[:path] ||= loc.expression.source_buffer.name.to_s
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
29
|
-
@memo[:
|
28
|
+
def test_line?
|
29
|
+
@memo[:test_line]
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
@memo[:
|
32
|
+
def test_line=(value)
|
33
|
+
@memo[:test_line] = value
|
34
34
|
end
|
35
35
|
|
36
36
|
def keep_line=(value)
|
data/lib/leftovers/config.rb
CHANGED
@@ -40,6 +40,10 @@ module Leftovers
|
|
40
40
|
@keep ||= ::Leftovers::MatcherBuilders::Node.build(yaml[:keep])
|
41
41
|
end
|
42
42
|
|
43
|
+
def test_only
|
44
|
+
@test_only ||= ::Leftovers::MatcherBuilders::Node.build(yaml[:test_only])
|
45
|
+
end
|
46
|
+
|
43
47
|
def requires
|
44
48
|
@requires ||= Array(yaml[:requires])
|
45
49
|
end
|
@@ -445,7 +445,7 @@ module Leftovers
|
|
445
445
|
{ '$ref' => '#/definitions/dynamic' }
|
446
446
|
]
|
447
447
|
},
|
448
|
-
'
|
448
|
+
'keepTestOnly' => {
|
449
449
|
'anyOf' => [
|
450
450
|
{ '$ref' => '#/definitions/string' },
|
451
451
|
{
|
@@ -460,7 +460,7 @@ module Leftovers
|
|
460
460
|
'has_prefix' => true, 'has_suffix' => true, 'matches' => true,
|
461
461
|
'path' => true, 'paths' => true,
|
462
462
|
'has_argument' => true, 'has_arguments' => true,
|
463
|
-
'unless' => { '$ref' => '#/definitions/
|
463
|
+
'unless' => { '$ref' => '#/definitions/keepTestOnlyList' }
|
464
464
|
},
|
465
465
|
'additionalProperties' => false,
|
466
466
|
'minProperties' => 1
|
@@ -469,15 +469,15 @@ module Leftovers
|
|
469
469
|
}
|
470
470
|
]
|
471
471
|
},
|
472
|
-
'
|
472
|
+
'keepTestOnlyList' => {
|
473
473
|
'anyOf' => [
|
474
474
|
{
|
475
475
|
'type' => 'array',
|
476
|
-
'items' => { '$ref' => '#/definitions/
|
476
|
+
'items' => { '$ref' => '#/definitions/keepTestOnly' },
|
477
477
|
'minItems' => 1,
|
478
478
|
'uniqueItems' => true
|
479
479
|
},
|
480
|
-
{ '$ref' => '#/definitions/
|
480
|
+
{ '$ref' => '#/definitions/keepTestOnly' }
|
481
481
|
]
|
482
482
|
}
|
483
483
|
},
|
@@ -487,7 +487,8 @@ module Leftovers
|
|
487
487
|
'test_paths' => { '$ref' => '#/definitions/stringList' },
|
488
488
|
'requires' => { '$ref' => '#/definitions/stringList' },
|
489
489
|
'gems' => { '$ref' => '#/definitions/stringList' },
|
490
|
-
'keep' => { '$ref' => '#/definitions/
|
490
|
+
'keep' => { '$ref' => '#/definitions/keepTestOnlyList' },
|
491
|
+
'test_only' => { '$ref' => '#/definitions/keepTestOnlyList' },
|
491
492
|
'dynamic' => { '$ref' => '#/definitions/dynamicList' }
|
492
493
|
}
|
493
494
|
}.freeze
|
data/lib/leftovers/definition.rb
CHANGED
@@ -9,11 +9,11 @@ module Leftovers
|
|
9
9
|
|
10
10
|
def initialize(
|
11
11
|
name,
|
12
|
-
method_node: nil,
|
13
12
|
location: method_node.loc.expression,
|
14
|
-
test: method_node.
|
13
|
+
test: method_node.test_line?
|
15
14
|
)
|
16
15
|
@name = name
|
16
|
+
@path = location.source_buffer.name.to_s
|
17
17
|
@location_source_line = location.source_line.to_s
|
18
18
|
@location_column_range_begin = location.column_range.begin.to_i
|
19
19
|
@location_column_range_end = location.column_range.end.to_i
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
# To give to matchers before creating a Definition
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
class DefinitionNode
|
7
|
+
attr_reader :path, :name
|
8
|
+
|
9
|
+
def initialize(name, path)
|
10
|
+
@name = name
|
11
|
+
@path = path
|
12
|
+
|
13
|
+
freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
# these are the methods checked by things in lib/leftovers/matchers
|
17
|
+
def kwargs
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def positional_arguments
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# these two i'm not sure are possible with the current config flags
|
26
|
+
# :nocov:
|
27
|
+
def scalar?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def type
|
32
|
+
:leftovers_definition
|
33
|
+
end
|
34
|
+
# :nocov:
|
35
|
+
end
|
36
|
+
end
|
@@ -1,18 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Leftovers
|
4
|
-
class DefinitionSet
|
4
|
+
class DefinitionSet
|
5
5
|
attr_reader :definitions
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
definitions,
|
9
|
-
method_node: nil,
|
10
|
-
location: method_node.loc.expression,
|
11
|
-
test: method_node.test?
|
12
|
-
)
|
7
|
+
def initialize(definitions)
|
13
8
|
@definitions = definitions
|
14
9
|
|
15
|
-
|
10
|
+
freeze
|
16
11
|
end
|
17
12
|
|
18
13
|
def names
|
@@ -23,10 +18,22 @@ module Leftovers
|
|
23
18
|
@definitions.map(&:to_s).join(', ')
|
24
19
|
end
|
25
20
|
|
21
|
+
def location_s
|
22
|
+
@definitions.first.location_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def highlighted_source(*args)
|
26
|
+
@definitions.first.highlighted_source(*args)
|
27
|
+
end
|
28
|
+
|
26
29
|
def in_collection?
|
27
30
|
@definitions.any?(&:in_collection?)
|
28
31
|
end
|
29
32
|
|
33
|
+
def test?
|
34
|
+
@definitions.any?(&:test?)
|
35
|
+
end
|
36
|
+
|
30
37
|
def in_test_collection?
|
31
38
|
@definitions.any?(&:in_test_collection?)
|
32
39
|
end
|
@@ -57,7 +57,7 @@ module Leftovers
|
|
57
57
|
NAME_RE = Regexp.union(METHOD_NAME_RE, NON_ALNUM_METHOD_NAME_RE, CONSTANT_NAME_RE)
|
58
58
|
LEFTOVERS_CALL_RE = /\bleftovers:call(?:s|ed|er|ers|) (#{NAME_RE}(?:[, :]+#{NAME_RE})*)/.freeze
|
59
59
|
LEFTOVERS_ALLOW_RE = /\bleftovers:(?:keeps?|skip(?:s|ped|)|allow(?:s|ed|))\b/.freeze
|
60
|
-
LEFTOVERS_TEST_RE = /\bleftovers:(?:for_tests?|tests?|testing)\b/.freeze
|
60
|
+
LEFTOVERS_TEST_RE = /\bleftovers:(?:for_tests?|tests?|testing|test_only)\b/.freeze
|
61
61
|
def process_comments(comments) # rubocop:disable Metrics/AbcSize
|
62
62
|
comments.each do |comment|
|
63
63
|
@allow_lines << comment.loc.line if comment.text.match?(LEFTOVERS_ALLOW_RE)
|
@@ -171,15 +171,20 @@ module Leftovers
|
|
171
171
|
|
172
172
|
private
|
173
173
|
|
174
|
-
def
|
175
|
-
@file.test? ||
|
174
|
+
def test_line?(loc)
|
175
|
+
@file.test? ||
|
176
|
+
@test_lines.include?(loc.line)
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_node?(node, loc)
|
180
|
+
test_line?(loc) || ::Leftovers.config.test_only === node
|
176
181
|
end
|
177
182
|
|
178
183
|
def add_definition(node, name: node.name, loc: node.loc.name)
|
179
184
|
return if @allow_lines.include?(loc.line)
|
180
185
|
return if Leftovers.config.keep === node
|
181
186
|
|
182
|
-
definitions << Leftovers::Definition.new(name, location: loc, test:
|
187
|
+
definitions << Leftovers::Definition.new(name, location: loc, test: test_node?(node, loc))
|
183
188
|
end
|
184
189
|
|
185
190
|
def add_call(name)
|
@@ -222,7 +227,7 @@ module Leftovers
|
|
222
227
|
|
223
228
|
def collect_dynamic(node) # rubocop:disable Metrics/AbcSize
|
224
229
|
node.keep_line = @allow_lines.include?(node.loc.line)
|
225
|
-
node.
|
230
|
+
node.test_line = test_line?(node.loc) unless node.keep_line?
|
226
231
|
|
227
232
|
Leftovers.config.dynamic.process(node, self)
|
228
233
|
rescue StandardError => e
|
@@ -64,6 +64,10 @@ module Leftovers
|
|
64
64
|
@keep ||= ::Leftovers::MatcherBuilders::Or.build(@configs.map(&:keep))
|
65
65
|
end
|
66
66
|
|
67
|
+
def test_only
|
68
|
+
@test_only ||= ::Leftovers::MatcherBuilders::Or.build(@configs.map(&:test_only))
|
69
|
+
end
|
70
|
+
|
67
71
|
private
|
68
72
|
|
69
73
|
def load_bundled_gem_config
|
@@ -9,7 +9,7 @@ module Leftovers
|
|
9
9
|
freeze
|
10
10
|
end
|
11
11
|
|
12
|
-
def process(str, node, method_node)
|
12
|
+
def process(str, node, method_node)
|
13
13
|
definitions = @then_processors.map do |then_processor|
|
14
14
|
processed = then_processor.process(str, node, method_node)
|
15
15
|
return if processed == :keep # rubocop:disable Lint/NonLocalExitFromIterator
|
@@ -22,11 +22,7 @@ module Leftovers
|
|
22
22
|
|
23
23
|
return definitions.first if definitions.length <= 1
|
24
24
|
|
25
|
-
::Leftovers::DefinitionSet.new(
|
26
|
-
definitions,
|
27
|
-
location: node.loc.expression,
|
28
|
-
method_node: method_node
|
29
|
-
)
|
25
|
+
::Leftovers::DefinitionSet.new(definitions)
|
30
26
|
end
|
31
27
|
end
|
32
28
|
end
|
@@ -11,12 +11,14 @@ module Leftovers
|
|
11
11
|
return unless str
|
12
12
|
return if str.empty?
|
13
13
|
|
14
|
-
|
14
|
+
str_node = Leftovers::DefinitionNode.new(str.to_sym, method_node.path)
|
15
|
+
|
16
|
+
return :keep if ::Leftovers.config.keep === str_node
|
15
17
|
|
16
18
|
Leftovers::Definition.new(
|
17
|
-
|
19
|
+
str_node.name,
|
18
20
|
location: node.loc.expression,
|
19
|
-
|
21
|
+
test: method_node.test_line? || ::Leftovers.config.test_only === str_node
|
20
22
|
)
|
21
23
|
end
|
22
24
|
end
|
data/lib/leftovers/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: leftovers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dana Sherson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -313,6 +313,7 @@ files:
|
|
313
313
|
- lib/leftovers/config_validator/error_processor.rb
|
314
314
|
- lib/leftovers/config_validator/schema_hash.rb
|
315
315
|
- lib/leftovers/definition.rb
|
316
|
+
- lib/leftovers/definition_node.rb
|
316
317
|
- lib/leftovers/definition_set.rb
|
317
318
|
- lib/leftovers/dynamic_processors.rb
|
318
319
|
- lib/leftovers/dynamic_processors/call.rb
|
@@ -438,8 +439,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
438
439
|
- !ruby/object:Gem::Version
|
439
440
|
version: '0'
|
440
441
|
requirements: []
|
441
|
-
|
442
|
-
rubygems_version: 2.7.6
|
442
|
+
rubygems_version: 3.1.2
|
443
443
|
signing_key:
|
444
444
|
specification_version: 4
|
445
445
|
summary: Find unused methods and classes/modules
|