leftovers 0.4.0 → 0.4.1
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 +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
|