leftovers 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/docs/Configuration.md +46 -11
  4. data/lib/config/actioncable.yml +4 -0
  5. data/lib/config/actionmailer.yml +22 -0
  6. data/lib/config/actionpack.yml +190 -0
  7. data/lib/config/actionview.yml +64 -0
  8. data/lib/config/activejob.yml +29 -0
  9. data/lib/config/activemodel.yml +74 -0
  10. data/lib/config/activerecord.yml +179 -0
  11. data/lib/config/activesupport.yml +98 -0
  12. data/lib/config/haml.yml +2 -0
  13. data/lib/config/rails.yml +11 -450
  14. data/lib/config/ruby.yml +6 -0
  15. data/lib/leftovers/ast/node.rb +14 -0
  16. data/lib/leftovers/config.rb +8 -0
  17. data/lib/leftovers/config_validator/schema_hash.rb +50 -5
  18. data/lib/leftovers/file.rb +2 -3
  19. data/lib/leftovers/matcher_builders/node.rb +2 -0
  20. data/lib/leftovers/matcher_builders/node_has_argument.rb +11 -7
  21. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +14 -10
  22. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +17 -13
  23. data/lib/leftovers/matcher_builders/node_has_receiver.rb +15 -0
  24. data/lib/leftovers/matcher_builders/node_type.rb +7 -6
  25. data/lib/leftovers/matcher_builders/node_value.rb +42 -0
  26. data/lib/leftovers/matcher_builders.rb +3 -2
  27. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +4 -1
  28. data/lib/leftovers/matchers/node_has_positional_argument.rb +0 -4
  29. data/lib/leftovers/matchers/node_has_receiver.rb +20 -0
  30. data/lib/leftovers/matchers/predicate.rb +19 -0
  31. data/lib/leftovers/matchers.rb +2 -0
  32. data/lib/leftovers/merged_config.rb +19 -1
  33. data/lib/leftovers/todo_reporter.rb +9 -6
  34. data/lib/leftovers/version.rb +1 -1
  35. data/lib/leftovers.rb +95 -92
  36. metadata +14 -3
  37. 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
@@ -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
 
@@ -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
@@ -91,7 +91,7 @@ module Leftovers
91
91
  },
92
92
  'valueType' => {
93
93
  'type' => 'string',
94
- 'enum' => %w{String Symbol Integer Float}
94
+ 'enum' => %w{String Symbol Integer Float Array Hash Proc}
95
95
  },
96
96
  'valueTypeList' => {
97
97
  'anyOf' => [
@@ -110,7 +110,41 @@ module Leftovers
110
110
  { 'type' => 'integer' },
111
111
  { 'type' => 'number' },
112
112
  { 'type' => 'boolean' },
113
- { 'type' => 'null' }
113
+ { 'type' => 'null' },
114
+ { 'allOf' => [
115
+ { '$ref' => '#/definitions/stringPattern' },
116
+ {
117
+ 'type' => 'object',
118
+ 'properties' => {
119
+ 'match' => true, 'matches' => true,
120
+ 'has_prefix' => true, 'has_suffix' => true,
121
+ 'at' => { '$ref' => '#/definitions/argumentPositionList' },
122
+ 'has_value' => { '$ref' => '#/definitions/hasValueList' },
123
+ 'has_receiver' => { '$ref' => '#/definitions/hasValueList' },
124
+ 'type' => { '$ref' => '#/definitions/valueTypeList' },
125
+ 'unless' => { '$ref' => '#/definitions/hasValueList' }
126
+ },
127
+ 'minProperties' => 1,
128
+ 'additionalProperties' => false,
129
+ 'allOf' => [
130
+ # incompatible groups
131
+ { 'not' => { 'required' => %w{match at} } },
132
+ { 'not' => { 'required' => %w{match has_value} } },
133
+ { 'not' => { 'required' => %w{match type} } },
134
+ { 'not' => { 'required' => %w{matches at} } },
135
+ { 'not' => { 'required' => %w{matches has_value} } },
136
+ { 'not' => { 'required' => %w{matches type} } },
137
+ { 'not' => { 'required' => %w{has_prefix at} } },
138
+ { 'not' => { 'required' => %w{has_prefix has_value} } },
139
+ { 'not' => { 'required' => %w{has_prefix type} } },
140
+ { 'not' => { 'required' => %w{has_suffix at} } },
141
+ { 'not' => { 'required' => %w{has_suffix has_value} } },
142
+ { 'not' => { 'required' => %w{has_suffix type} } },
143
+ { 'not' => { 'required' => %w{at type} } },
144
+ { 'not' => { 'required' => %w{has_value type} } }
145
+ ]
146
+ }
147
+ ] }
114
148
  ]
115
149
  },
116
150
  'hasValueList' => {
@@ -133,11 +167,14 @@ module Leftovers
133
167
  'properties' => {
134
168
  'at' => { '$ref' => '#/definitions/argumentPositionList' },
135
169
  'has_value' => { '$ref' => '#/definitions/hasValueList' },
136
- 'has_value_type' => { '$ref' => '#/definitions/valueTypeList' },
137
170
  'unless' => { '$ref' => '#/definitions/hasArgumentList' }
138
171
  },
139
172
  'minProperties' => 1,
140
- 'additionalProperties' => false
173
+ 'additionalProperties' => false,
174
+ 'allOf' => [
175
+ # synonyms
176
+ { 'not' => { 'required' => %w{has_argument has_arguments} } }
177
+ ]
141
178
  }
142
179
  ]
143
180
  },
@@ -160,7 +197,8 @@ module Leftovers
160
197
  'path' => { '$ref' => '#/definitions/stringList' },
161
198
  'paths' => { '$ref' => '#/definitions/stringList' },
162
199
  'has_argument' => { '$ref' => '#/definitions/hasArgumentList' },
163
- 'has_arguments' => { '$ref' => '#/definitions/hasArgumentList' }
200
+ 'has_arguments' => { '$ref' => '#/definitions/hasArgumentList' },
201
+ 'has_receiver' => { '$ref' => '#/definitions/hasValueList' }
164
202
  },
165
203
  'minProperties' => 1,
166
204
  'allOf' => [
@@ -390,6 +428,7 @@ module Leftovers
390
428
  { 'required' => ['name'] }, { 'required' => ['names'] },
391
429
  { 'required' => ['path'] }, { 'required' => ['paths'] },
392
430
  { 'required' => ['has_argument'] }, { 'required' => ['has_arguments'] },
431
+ { 'required' => ['has_receiver'] },
393
432
  { 'required' => ['unless'] }
394
433
  ] },
395
434
  {
@@ -399,6 +438,7 @@ module Leftovers
399
438
  'name' => true, 'names' => true,
400
439
  'path' => true, 'paths' => true,
401
440
  'has_argument' => true, 'has_arguments' => true,
441
+ 'has_receiver' => true,
402
442
  'unless' => { '$ref' => '#/definitions/ruleMatcherList' }
403
443
 
404
444
  },
@@ -415,6 +455,7 @@ module Leftovers
415
455
  { 'required' => ['name'] }, { 'required' => ['names'] },
416
456
  { 'required' => ['path'] }, { 'required' => ['paths'] },
417
457
  { 'required' => ['has_argument'] }, { 'required' => ['has_arguments'] },
458
+ { 'required' => ['has_receiver'] },
418
459
  { 'required' => ['unless'] }
419
460
  ] },
420
461
  {
@@ -424,6 +465,7 @@ module Leftovers
424
465
  'name' => true, 'names' => true,
425
466
  'path' => true, 'paths' => true,
426
467
  'has_argument' => true, 'has_arguments' => true,
468
+ 'has_receiver' => true,
427
469
  'unless' => { '$ref' => '#/definitions/ruleMatcherList' },
428
470
 
429
471
  'call' => true, 'calls' => true,
@@ -460,6 +502,7 @@ module Leftovers
460
502
  'has_prefix' => true, 'has_suffix' => true, 'matches' => true,
461
503
  'path' => true, 'paths' => true,
462
504
  'has_argument' => true, 'has_arguments' => true,
505
+ 'has_receiver' => true,
463
506
  'unless' => { '$ref' => '#/definitions/keepTestOnlyList' }
464
507
  },
465
508
  'additionalProperties' => false,
@@ -485,6 +528,8 @@ module Leftovers
485
528
  'include_paths' => { '$ref' => '#/definitions/stringList' },
486
529
  'exclude_paths' => { '$ref' => '#/definitions/stringList' },
487
530
  'test_paths' => { '$ref' => '#/definitions/stringList' },
531
+ 'haml_paths' => { '$ref' => '#/definitions/stringList' },
532
+ 'erb_paths' => { '$ref' => '#/definitions/stringList' },
488
533
  'requires' => { '$ref' => '#/definitions/stringList' },
489
534
  'gems' => { '$ref' => '#/definitions/stringList' },
490
535
  'keep' => { '$ref' => '#/definitions/keepTestOnlyList' },
@@ -15,10 +15,9 @@ module Leftovers
15
15
  end
16
16
 
17
17
  def ruby
18
- case extname
19
- when '.haml'
18
+ if Leftovers.config.haml_paths.allowed?(relative_path)
20
19
  ::Leftovers::Haml.precompile(read, self)
21
- when '.rhtml', '.rjs', '.erb'
20
+ elsif Leftovers.config.erb_paths.allowed?(relative_path)
22
21
  ::Leftovers::ERB.precompile(read)
23
22
  else
24
23
  read
@@ -21,6 +21,7 @@ module Leftovers
21
21
  names: nil, match: nil, has_prefix: nil, has_suffix: nil,
22
22
  paths: nil,
23
23
  has_arguments: nil,
24
+ has_receiver: nil,
24
25
  unless_arg: nil
25
26
  )
26
27
  ::Leftovers::MatcherBuilders::And.build([
@@ -30,6 +31,7 @@ module Leftovers
30
31
  ]),
31
32
  ::Leftovers::MatcherBuilders::NodePath.build(paths),
32
33
  ::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
34
+ ::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
33
35
  ::Leftovers::MatcherBuilders::Unless.build(
34
36
  (::Leftovers::MatcherBuilders::Node.build(unless_arg) if unless_arg)
35
37
  )