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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02f0f5136df6e16a7d27e47d118446f9118395f9242e29a32c91476ccd070591
4
- data.tar.gz: fa438c525a212769b17cae1b2e2f05495c2772da5c9f3a05c9dd2d869743e969
3
+ metadata.gz: a3fb0707b239e6e7581c2997969483c72b3ff272895173828fc3434c08de165a
4
+ data.tar.gz: aadfba4e9fc93b110599c8e2bd66f723efbce39cabf4deda036d904358cfa131
5
5
  SHA512:
6
- metadata.gz: 3c88300e0a1e822f510dd22ff72a91ab1db5ed35ac7cdd323ec3fe194f347748faad08efd62ac727501ed6f854e5623b6958589e216a4e2389ed44f9fc878b54
7
- data.tar.gz: '08deaf4ffb911b2a1d53960e5bfc6c46a3990d0a6197d28f18b8ccfc60031b48c3701dca1e1d1ffe7db5e1ab892b1630c9332e87706769326141b0793115a2d6'
6
+ metadata.gz: 129fe2d42ec0f47d9f76105c1d53f0209133864d77688db231cb9fbc3c5ad3e6ea3ea8bdd95b1902b480b8a7e78709f2c197b261e1132ae0ce3cddc618e39899
7
+ data.tar.gz: 1d01550bdf1762344c2744d21f01c1590b928a751439714e5ad364211b2a914aec486415f1d5769113b1d3bf23023319c3d68bf72b733367dc7851fdc9e4ffb9
@@ -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 with `skip: true` in the configuration file.
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:test`
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:test`
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:test
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.
@@ -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
@@ -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")
@@ -25,12 +25,12 @@ module Leftovers
25
25
  @memo[:path] ||= loc.expression.source_buffer.name.to_s
26
26
  end
27
27
 
28
- def test?
29
- @memo[:test]
28
+ def test_line?
29
+ @memo[:test_line]
30
30
  end
31
31
 
32
- def test=(value)
33
- @memo[:test] = value
32
+ def test_line=(value)
33
+ @memo[:test_line] = value
34
34
  end
35
35
 
36
36
  def keep_line=(value)
@@ -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
- 'keep' => {
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/keepList' }
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
- 'keepList' => {
472
+ 'keepTestOnlyList' => {
473
473
  'anyOf' => [
474
474
  {
475
475
  'type' => 'array',
476
- 'items' => { '$ref' => '#/definitions/keep' },
476
+ 'items' => { '$ref' => '#/definitions/keepTestOnly' },
477
477
  'minItems' => 1,
478
478
  'uniqueItems' => true
479
479
  },
480
- { '$ref' => '#/definitions/keep' }
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/keepList' },
490
+ 'keep' => { '$ref' => '#/definitions/keepTestOnlyList' },
491
+ 'test_only' => { '$ref' => '#/definitions/keepTestOnlyList' },
491
492
  'dynamic' => { '$ref' => '#/definitions/dynamicList' }
492
493
  }
493
494
  }.freeze
@@ -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.test?
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 < ::Leftovers::Definition
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
- super
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 test?(loc)
175
- @file.test? || @test_lines.include?(loc.line)
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: test?(loc))
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.test = test?(node.loc) unless node.keep_line?
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) # rubocop:disable Metrics/MethodLength
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
- return :keep if ::Leftovers.config.keep === node
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
- str.to_sym,
19
+ str_node.name,
18
20
  location: node.loc.expression,
19
- method_node: method_node
21
+ test: method_node.test_line? || ::Leftovers.config.test_only === str_node
20
22
  )
21
23
  end
22
24
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
- VERSION = '0.4.0'
4
+ VERSION = '0.4.1'
5
5
  end
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.0
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-03 00:00:00.000000000 Z
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
- rubyforge_project:
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