leftovers 0.4.0 → 0.5.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/README.md +37 -4
  4. data/docs/Configuration.md +75 -11
  5. data/leftovers.gemspec +1 -0
  6. data/lib/config/actioncable.yml +4 -0
  7. data/lib/config/actionmailer.yml +22 -0
  8. data/lib/config/actionpack.yml +190 -0
  9. data/lib/config/actionview.yml +64 -0
  10. data/lib/config/activejob.yml +29 -0
  11. data/lib/config/activemodel.yml +74 -0
  12. data/lib/config/activerecord.yml +179 -0
  13. data/lib/config/activesupport.yml +98 -0
  14. data/lib/config/haml.yml +2 -0
  15. data/lib/config/rails.yml +11 -450
  16. data/lib/config/ruby.yml +6 -0
  17. data/lib/leftovers/ast/node.rb +18 -4
  18. data/lib/leftovers/cli.rb +13 -4
  19. data/lib/leftovers/collector.rb +2 -1
  20. data/lib/leftovers/config.rb +12 -0
  21. data/lib/leftovers/config_validator/schema_hash.rb +57 -11
  22. data/lib/leftovers/definition.rb +6 -6
  23. data/lib/leftovers/definition_node.rb +36 -0
  24. data/lib/leftovers/definition_set.rb +15 -8
  25. data/lib/leftovers/file.rb +2 -3
  26. data/lib/leftovers/file_collector.rb +10 -5
  27. data/lib/leftovers/matcher_builders/node.rb +2 -0
  28. data/lib/leftovers/matcher_builders/node_has_argument.rb +11 -7
  29. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +14 -10
  30. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +17 -13
  31. data/lib/leftovers/matcher_builders/node_has_receiver.rb +15 -0
  32. data/lib/leftovers/matcher_builders/node_type.rb +7 -6
  33. data/lib/leftovers/matcher_builders/node_value.rb +42 -0
  34. data/lib/leftovers/matcher_builders.rb +3 -2
  35. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +4 -1
  36. data/lib/leftovers/matchers/node_has_positional_argument.rb +0 -4
  37. data/lib/leftovers/matchers/node_has_receiver.rb +20 -0
  38. data/lib/leftovers/matchers/predicate.rb +19 -0
  39. data/lib/leftovers/matchers.rb +2 -0
  40. data/lib/leftovers/merged_config.rb +28 -1
  41. data/lib/leftovers/reporter.rb +56 -4
  42. data/lib/leftovers/todo_reporter.rb +127 -0
  43. data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -6
  44. data/lib/leftovers/value_processors/return_definition.rb +5 -3
  45. data/lib/leftovers/version.rb +1 -1
  46. data/lib/leftovers.rb +94 -96
  47. metadata +31 -5
  48. data/lib/leftovers/matcher_builders/argument_node_value.rb +0 -21
data/lib/config/rails.yml CHANGED
@@ -1,457 +1,18 @@
1
-
2
- exclude_paths:
3
- - db/migrate/*
4
- include_paths:
5
- - '*.rjs'
6
- - '*.rhtml'
7
- requires:
8
- - 'active_support/core_ext/string'
9
- - 'active_support/inflections'
10
- - './config/initializers/inflections'
11
-
12
1
  # THIS IS INCOMPLETE (you can help by expanding it)
13
2
  # rails is _really complicated_ and has a lot of magic which calls methods for you.
14
3
  # some is currently impossible to handle (with_options).
15
4
  # Some is just corners of rails I haven't hit yet.
5
+ gems:
6
+ - actioncable
7
+ - actionmailer
8
+ - actionpack
9
+ - actionview
10
+ - activejob
11
+ - activemodel
12
+ - activerecord
13
+ - activesupport
14
+
16
15
  keep:
17
- - ClassMethods # ActiveSupport::Concern
18
- - process_action # ActiveSupport::LogSubscriber
19
- - validate_each # ActiveModel::EachValidator
20
- - format_message # ActiveSupport::Logger
21
- - ssl_configured? # ApplicationController
22
- - default_url_options # called by url_for
16
+ - default_url_options # called by url_for, unsure what gem does
23
17
  - APP_PATH
24
18
  - APP_ROOT
25
- - has_suffix: Helper
26
- path: /app/helpers
27
- - has_suffix: Preview
28
- path: '**/mailers/previews/**/*_preview.rb'
29
-
30
- dynamic:
31
- - names:
32
- - after_initialize
33
- - after_find
34
- - after_touch
35
- - before_validation
36
- - after_validation
37
- - before_save
38
- - around_save
39
- - after_save
40
- - before_create
41
- - around_create
42
- - after_create
43
- - before_update
44
- - around_update
45
- - after_update
46
- - before_destroy
47
- - around_destroy
48
- - after_destroy
49
- - after_commit
50
- - after_rollback
51
- - after_create_commit
52
- - after_update_commit
53
- - after_destroy_commit
54
- - after_save_commit
55
- calls:
56
- - arguments: 0
57
- - arguments: [if, unless]
58
- nested:
59
- arguments: '*'
60
- - name:
61
- - after_action
62
- - append_after_action
63
- - append_around_action
64
- - append_before_action
65
- - around_action
66
- - before_action
67
- - prepend_after_action
68
- - prepend_around_action
69
- - prepend_before_action
70
- - skip_before_action
71
- - skip_after_action
72
- - skip_around_action
73
- - validates_associated
74
- calls:
75
- - arguments: ['*', if, unless]
76
- - name: validates
77
- calls:
78
- - arguments:
79
- - '*'
80
- - within
81
- - inclusion
82
- - scope
83
- - if
84
- - unless
85
- - arguments: inclusion
86
- nested:
87
- arguments: 'in'
88
- - keywords:
89
- unless: [if, unless]
90
- camelize: true
91
- add_suffix: Validator
92
- split: '::'
93
- - names:
94
- - validate
95
- - validate_associated
96
- calls:
97
- - arguments: ['*', if, unless]
98
- - name:
99
- - check_box
100
- - date_select
101
- - datetime_select
102
- - file_field
103
- - hidden_field
104
- - label
105
- - radio_button
106
- - select
107
- - time_select
108
- - time_zone_select
109
- - color_field
110
- - date_field
111
- - datetime_field
112
- - datetime_local_field
113
- - email_field
114
- - month_field
115
- - number_field
116
- - password_field
117
- - phone_field
118
- - range_field
119
- - search_field
120
- - telephone_field
121
- - text_area
122
- - text_field
123
- - time_field
124
- - url_field
125
- - week_field
126
- calls:
127
- - arguments: [0,1] # 0: with a receiver, 1: with no receiver
128
- - arguments: [0,1]
129
- add_suffix: '='
130
- - name: fields_for
131
- calls:
132
- argument: 1
133
- add_suffix: _attributes
134
- - name: options_from_collection_for_select
135
- calls:
136
- - arguments: [1,2]
137
- - name:
138
- - collection_select
139
- - collection_check_boxes
140
- - collection_radio_buttons
141
- calls:
142
- - argument: 1
143
- add_suffix: '='
144
- - arguments: [3,4]
145
- - name: grouped_collection_select
146
- calls:
147
- - argument: 1
148
- add_suffix: '='
149
- - arguments: [3,4,5,6]
150
- - name: option_groups_from_collection_for_select
151
- calls:
152
- - arguments: [0,1,2,3]
153
- - name: scope
154
- path: /app/models
155
- defines:
156
- argument: 0 # ar
157
- - name: scope
158
- path: /config/routes*
159
- calls:
160
- argument: module # routes
161
- camelize: true
162
- split: '::'
163
- - name: namespace
164
- calls:
165
- - argument: 0
166
- camelize: true
167
- split: '::'
168
- - name:
169
- - attribute
170
- - alias_attribute
171
- path: app/models/*
172
- defines:
173
- argument: 0
174
- transforms:
175
- - original
176
- - add_suffix: '?'
177
- - add_suffix: '='
178
- - name: alias_attribute
179
- calls:
180
- - argument: 1
181
- - argument: 1
182
- add_suffix: '?'
183
- - argument: 1
184
- add_suffix: '='
185
- - name:
186
- - has_one
187
- - belongs_to
188
- unless:
189
- has_argument: class_name
190
- calls:
191
- argument: 0
192
- camelize: true
193
- split: '::'
194
-
195
- - name:
196
- - has_many
197
- - has_and_belongs_to_many
198
- unless:
199
- has_argument: class_name
200
- calls:
201
- - argument: 0
202
- camelize: true
203
- singularize: true
204
- split: '::'
205
- - name:
206
- - has_many
207
- - has_and_belongs_to_many
208
- defines:
209
- - argument: 0
210
- transforms:
211
- - original
212
- - add_suffix: '='
213
- - singularize: true
214
- add_suffix: _ids
215
- - singularize: true
216
- add_suffix: _ids=
217
- - name:
218
- - has_many
219
- - has_one
220
- - has_and_belongs_to_many
221
- calls:
222
- argument:
223
- - as
224
- - name:
225
- - has_one
226
- - has_many
227
- calls:
228
- - argument:
229
- - source_type
230
- - source
231
- - through
232
- - name:
233
- - has_one
234
- - belongs_to
235
- defines:
236
- - argument: 0
237
- transforms:
238
- - original
239
- - add_suffix: '='
240
- - add_prefix: build_
241
- - add_prefix: create_
242
- - add_prefix: create_
243
- add_suffix: '!'
244
- - add_prefix: reload
245
- - name: belongs_to
246
- unless:
247
- has_argument:
248
- at: optional
249
- has_value: true
250
- calls:
251
- argument: 0
252
-
253
- - name:
254
- - has_one
255
- - has_many
256
- - belongs_to
257
- - has_and_belongs_to_many
258
- calls:
259
- - argument: class_name
260
- split: '::'
261
- - argument: inverse_of
262
- - argument: touch
263
- add_suffix: '='
264
- - name:
265
- - has_one
266
- - has_many
267
- - belongs_to
268
- - has_and_belongs_to_many
269
- has_argument:
270
- at: [dependent, inverse_of, touch, validate]
271
- unless:
272
- has_value: false
273
- calls:
274
- argument: 0
275
-
276
- - name:
277
- - rescue_from
278
- calls:
279
- - argument: with
280
- - name:
281
- - match
282
- - delete
283
- - get
284
- - patch
285
- - post
286
- - put
287
- - root
288
- calls:
289
- - arguments: [0, action]
290
- - argument: '**'
291
- delete_before: '#'
292
- - argument: '**'
293
- delete_after: '#'
294
- camelize: true
295
- add_suffix: Controller
296
- split: '::'
297
- - name: delegate
298
- has_argument:
299
- at: prefix
300
- has_value: true
301
- defines:
302
- - argument: '*'
303
- add_prefix:
304
- argument: to
305
- add_suffix: '_'
306
- calls:
307
- - argument: to
308
- - argument: '*'
309
- - name: delegate
310
- has_argument:
311
- at: prefix
312
- has_value_type: [String, Symbol]
313
- defines:
314
- - argument: '*'
315
- add_prefix:
316
- argument: prefix
317
- add_suffix: '_'
318
- calls:
319
- - argument: to
320
- - argument: '*'
321
- - name: delegate
322
- unless:
323
- has_argument:
324
- - at: prefix
325
- has_value: true
326
- - at: prefix
327
- has_value_type: [String, Symbol]
328
- calls:
329
- - argument: to
330
- - name:
331
- - resource
332
- - resources
333
- calls:
334
- - argument: only
335
- - argument: controller
336
- camelize: true
337
- add_suffix: Controller
338
- split: '::'
339
- - name:
340
- - resources
341
- - controller
342
- - namespace
343
- calls:
344
- - argument: 0
345
- camelize: true
346
- add_suffix: Controller
347
- split: '::'
348
- - name: accepts_nested_attributes_for
349
- defines:
350
- argument: '*'
351
- transforms:
352
- - add_suffix: _attributes
353
- - add_suffix: _attributes=
354
- calls:
355
- argument: reject_if
356
- - name: resource
357
- calls:
358
- - argument: 0
359
- camelize: true
360
- pluralize: true
361
- add_suffix: Controller
362
- split: '::'
363
- - name:
364
- - new
365
- - create
366
- - create!
367
- - update
368
- - update!
369
- - assign_attributes
370
- calls:
371
- keyword: '**'
372
- add_suffix: '='
373
- - name: permit
374
- calls:
375
- arguments: ['*', '**']
376
- keywords: '**'
377
- add_suffix: "="
378
- recursive: true
379
- - name: layout
380
- calls:
381
- argument: 0
382
- - name:
383
- - includes
384
- - preload
385
- - eager_load
386
- - joins
387
- - left_joins
388
- - left_outer_joins
389
- calls:
390
- arguments: ['*', '**']
391
- keywords: '**'
392
- - name:
393
- - string
394
- - text
395
- - integer
396
- - bigint
397
- - float
398
- - decimal
399
- - numeric
400
- - datetime
401
- - time
402
- - date
403
- - binary
404
- - boolean
405
- path: /db/schema.rb
406
- calls:
407
- argument: 0
408
- transforms:
409
- - original
410
- - add_suffix: '='
411
- - add_suffix: '?'
412
- - name:
413
- - cattr_accessor
414
- - mattr_accessor
415
- defines:
416
- - argument: '*'
417
- - argument: '*'
418
- add_suffix: '='
419
- calls:
420
- - argument: '*'
421
- add_prefix: '@'
422
- - name:
423
- - cattr_reader
424
- - mattr_reader
425
- defines:
426
- - argument: '*'
427
- calls:
428
- - argument: '*'
429
- add_prefix: '@'
430
- - name:
431
- - cattr_writer
432
- - mattr_writer
433
- defines:
434
- - argument: '*'
435
- add_suffix: '='
436
-
437
- - name:
438
- - thread_cattr_accessor
439
- - thread_mattr_accessor
440
- defines:
441
- - argument: '*'
442
- - argument: '*'
443
- add_suffix: '='
444
- - name:
445
- - thread_cattr_reader
446
- - thread_mattr_reader
447
- defines:
448
- argument: '*'
449
- - name:
450
- - thread_cattr_writer
451
- - thread_mattr_writer
452
- defines:
453
- argument: '*'
454
- add_suffix: '='
455
- - name: delegate_missing_to
456
- calls:
457
- argument: 0
data/lib/config/ruby.yml CHANGED
@@ -14,6 +14,12 @@ test_paths:
14
14
  - /tests/
15
15
  - /test/
16
16
 
17
+ erb_paths:
18
+ - '*.erb'
19
+
20
+ haml_paths:
21
+ - '*.haml'
22
+
17
23
  keep:
18
24
  - initialize # called by new
19
25
  - inspect # called by repl, to_s
@@ -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)
@@ -78,6 +78,13 @@ module Leftovers
78
78
  type == :str || type == :sym
79
79
  end
80
80
 
81
+ def proc?
82
+ return unless type == :block
83
+
84
+ name = first.name
85
+ name == :lambda || name == :proc
86
+ end
87
+
81
88
  def arguments
82
89
  @memo.fetch(:arguments) do
83
90
  @memo[:arguments] = case type
@@ -106,6 +113,13 @@ module Leftovers
106
113
  end
107
114
  end
108
115
 
116
+ def receiver
117
+ case type
118
+ when :const, :csend, :send
119
+ first
120
+ end
121
+ end
122
+
109
123
  def unwrap_freeze
110
124
  return self unless type == :send && name == :freeze
111
125
 
data/lib/leftovers/cli.rb CHANGED
@@ -28,20 +28,29 @@ module Leftovers
28
28
  Leftovers.progress = true
29
29
 
30
30
  opts.banner = 'Usage: leftovers [options]'
31
+
31
32
  opts.on('--[no-]parallel', 'Run in parallel or not, default --parallel') do |p|
32
33
  Leftovers.parallel = p
33
34
  end
35
+
34
36
  opts.on('--[no-]progress', 'Show progress counts or not, default --progress') do |p|
35
37
  Leftovers.progress = p
36
38
  end
37
- opts.on('-v', '--version', 'Returns the current version') do
38
- stdout.puts(Leftovers::VERSION)
39
- Leftovers.exit
40
- end
39
+
41
40
  opts.on('--dry-run', 'Output files that will be looked at') do
42
41
  Leftovers::FileList.new.each { |f| stdout.puts f.relative_path }
43
42
  Leftovers.exit
44
43
  end
44
+
45
+ opts.on('--write-todo', 'Outputs the unused items in a todo file to gradually fix') do
46
+ Leftovers.reporter = Leftovers::TodoReporter.new
47
+ end
48
+
49
+ opts.on('-v', '--version', 'Returns the current version') do
50
+ stdout.puts(Leftovers::VERSION)
51
+ Leftovers.exit
52
+ end
53
+
45
54
  opts.on('-h', '--help', 'Shows this message') do
46
55
  stdout.puts(opts.help)
47
56
  Leftovers.exit
@@ -18,6 +18,7 @@ module Leftovers
18
18
  end
19
19
 
20
20
  def collect
21
+ Leftovers.reporter.prepare
21
22
  collect_file_list(Leftovers::FileList.new)
22
23
  print_progress
23
24
  Leftovers.newline
@@ -46,7 +47,7 @@ module Leftovers
46
47
  )
47
48
  end
48
49
 
49
- def finish_file(_, _, result)
50
+ def finish_file(_item, _index, result)
50
51
  @count += 1
51
52
  @count_calls += result[:calls].length
52
53
  @count_definitions += result[:definitions].length
@@ -32,6 +32,14 @@ module Leftovers
32
32
  @test_paths ||= Array(yaml[:test_paths])
33
33
  end
34
34
 
35
+ def haml_paths
36
+ @haml_paths ||= Array(yaml[:haml_paths])
37
+ end
38
+
39
+ def erb_paths
40
+ @erb_paths ||= Array(yaml[:erb_paths])
41
+ end
42
+
35
43
  def dynamic
36
44
  @dynamic ||= ::Leftovers::ProcessorBuilders::Dynamic.build(yaml[:dynamic])
37
45
  end
@@ -40,6 +48,10 @@ module Leftovers
40
48
  @keep ||= ::Leftovers::MatcherBuilders::Node.build(yaml[:keep])
41
49
  end
42
50
 
51
+ def test_only
52
+ @test_only ||= ::Leftovers::MatcherBuilders::Node.build(yaml[:test_only])
53
+ end
54
+
43
55
  def requires
44
56
  @requires ||= Array(yaml[:requires])
45
57
  end