debride 1.14.0 → 1.15.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: 3a714288d6ecf460fcc966b8affc300f4bfe72da8e7d955e1345d757fbe389e9
4
- data.tar.gz: '0608d18319513d0193482b503def7a86b7fc1544dfffb1048849d74b0b0d1728'
3
+ metadata.gz: a141179f7eaccb00427a5f08718c4feb5f4cc71f088c85c9fa5ca9a2a9d11320
4
+ data.tar.gz: 90cf53e502fb9174beaba59f09f45c1c316c2c0179f5c35509523af2c0c49cb8
5
5
  SHA512:
6
- metadata.gz: c7faa53a9d8aaa8e1f6bb5673ac7619a357a34d75636eaaab43fc017814cac33805dcb0904385d19a4e1d32b95ccc6a01877083a379ee74e6c91847b4713e278
7
- data.tar.gz: ec449e3d4d5bdae20271e58d54da4dce6050866e56493d68f7ce236bb7829e51f342185576c5a772ee6e140e1855557598bd9062c5b9cc6f4d2112ea3fc16ed7
6
+ metadata.gz: e716a26676e9a6e3eef63dff026138910c7bd49ff4e89c0741f6be172cfe1e470a01944db3912555efc0e34a981fd6903164ee6a139795ed78e507bfa4911d7d
7
+ data.tar.gz: b4d27a4b57292cfd04ee94849cc42fbb281a9446ee850f5c3e049fdf4a6cc6fde04eeca89092dbf08147f52e5ba1dbf644145a62ea12eb9a95bd6557f2cc15ad
checksums.yaml.gz.sig CHANGED
Binary file
data/History.rdoc CHANGED
@@ -1,3 +1,24 @@
1
+ === 1.15.1 / 2026-01-26
2
+
3
+ * 1 bug fix:
4
+
5
+ * Namespace NotRubyParser to avoid problems with bundler's horrid eager loading. (nateberkopec)
6
+
7
+ === 1.15.0 / 2026-01-02
8
+
9
+ * 1 minor enhancement:
10
+
11
+ * Added process_hash to handle hash shortcut syntax in case it is a call. (TSMMark)
12
+
13
+ * 6 bug fixes:
14
+
15
+ * Bump prism dependency to 1.7+.
16
+ * Load debride with require_relative in bin/debride.
17
+ * Minor fixes for prism 1.7 and ruby 4.0.
18
+ * Oops! Fixed --legacy option definition.
19
+ * Properly handle scope/alias_method with interoplation. (alagos)
20
+ * Removed prism patches now that they've been upstreamed.
21
+
1
22
  === 1.14.0 / 2025-12-11
2
23
 
3
24
  * 2 minor enhancements:
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ Hoe::add_include_dirs("../../sexp_processor/dev/lib",
11
11
  "../../path_expander/dev/lib",
12
12
  "lib")
13
13
 
14
- Hoe.plugin :isolate
14
+ Hoe.plugin :isolate_binaries
15
15
  Hoe.plugin :seattlerb
16
16
  Hoe.plugin :rdoc
17
17
  Hoe.plugin :cov
@@ -21,7 +21,7 @@ Hoe.spec "debride" do
21
21
  license "MIT"
22
22
 
23
23
  dependency "sexp_processor", "~> 4.17"
24
- dependency "prism", "~> 1.5"
24
+ dependency "prism", "~> 1.7"
25
25
  dependency "path_expander", "~> 2.0"
26
26
  end
27
27
 
data/bin/debride CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env -S ruby -w
2
2
 
3
- require "debride"
3
+ require_relative "../lib/debride"
4
4
 
5
5
  Debride.run(ARGV).report
data/lib/debride.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "optparse"
4
4
  require "set"
5
5
  require "stringio"
6
+ require "timeout"
6
7
 
7
8
  require "sexp_processor"
8
9
  require "path_expander"
@@ -10,23 +11,15 @@ require "path_expander"
10
11
  require "prism"
11
12
  require "prism/translation/ruby_parser"
12
13
 
13
- unless Prism::Translation::RubyParser.method_defined? :process then
14
- class Prism::Translation::RubyParser # compatibility layer
15
- def process(ruby, file, timeout=nil) =
16
- Timeout.timeout(timeout) { parse ruby, file }
17
- end
18
- end
19
-
20
- class NotRubyParser < Prism::Translation::RubyParser # compatibility layer
21
- end
22
-
23
14
  ##
24
15
  # A static code analyzer that points out possible dead methods.
25
16
 
26
17
  class Debride < MethodBasedSexpProcessor
27
- VERSION = "1.14.0" # :nodoc:
18
+ VERSION = "1.15.1" # :nodoc:
28
19
  PROJECT = "debride"
29
20
 
21
+ NotRubyParser = Class.new Prism::Translation::RubyParser # compatibility layer :nodoc:
22
+
30
23
  def self.load_plugins proj = PROJECT
31
24
  unless defined? @@plugins then
32
25
  @@plugins = []
@@ -108,8 +101,8 @@ class Debride < MethodBasedSexpProcessor
108
101
  end
109
102
 
110
103
  parser = option[:parser].new
111
- parser.process(file, path, option[:timeout])
112
- rescue Racc::ParseError, RegexpError => e
104
+ parser.process file, path, option[:timeout]
105
+ rescue RubyParser::SyntaxError, RegexpError => e
113
106
  warn "Parse Error parsing #{path}. Skipping."
114
107
  warn " #{e.message}"
115
108
  rescue Timeout::Error
@@ -172,7 +165,7 @@ class Debride < MethodBasedSexpProcessor
172
165
  options[:minimum] = n
173
166
  end
174
167
 
175
- opts.on "--legacy" "Use RubyParser for parsing." do
168
+ opts.on "--legacy", "Use RubyParser for parsing." do
176
169
  require "ruby_parser"
177
170
  option[:parser] = RubyParser
178
171
  end
@@ -349,27 +342,30 @@ class Debride < MethodBasedSexpProcessor
349
342
  end
350
343
  when *RAILS_MACRO_METHODS
351
344
  # s(:call, nil, :has_one, s(:lit, :has_one_relation), ...)
352
- _, _, _, (_, name), * = sexp
345
+ _, _, _, name, * = sexp
353
346
 
354
347
  # try to detect route scope vs model scope
355
348
  if context.include? :module or context.include? :class then
356
- file, line = sexp.file, sexp.line
357
- record_method name, file, line
349
+ if string_like? name then
350
+ file, line = sexp.file, sexp.line
351
+ record_method name.last, file, line
352
+ end
358
353
  end
359
354
  when /_path$/ then
360
355
  method_name = method_name.to_s.delete_suffix("_path").to_sym if option[:rails]
361
356
  when /^deliver_/ then
362
357
  method_name = method_name.to_s.delete_prefix("deliver_").to_sym if option[:rails]
363
358
  when :alias_method then
359
+ # s(:call, nil, :alias_method, lhs, rhs)
364
360
  _, _, _, lhs, rhs = sexp
365
361
 
366
- if Sexp === lhs and Sexp === rhs then
367
- lhs = lhs.last
368
- rhs = rhs.last
362
+ if string_like? lhs and string_like? rhs then
363
+ lhs = lhs.last.to_sym
364
+ rhs = rhs.last.to_sym
369
365
 
370
366
  record_method lhs, sexp.file, sexp.line
371
367
 
372
- called << rhs
368
+ called << rhs # TODO: why?
373
369
  end
374
370
  end
375
371
 
@@ -380,6 +376,10 @@ class Debride < MethodBasedSexpProcessor
380
376
  sexp
381
377
  end
382
378
 
379
+ def string_like? s
380
+ Sexp === s and %i[lit str].include?(s.sexp_type)
381
+ end
382
+
383
383
  def process_alias exp
384
384
  _, (_, lhs), (_, rhs) = exp
385
385
 
@@ -482,6 +482,21 @@ class Debride < MethodBasedSexpProcessor
482
482
 
483
483
  alias process_safe_call process_call
484
484
 
485
+ def process_hash sexp
486
+ _, *pairs = sexp
487
+
488
+ pairs.each_slice 2 do |k, v|
489
+ if v.nil? && k.sexp_type == :lit then
490
+ called << k.last
491
+ else
492
+ process k
493
+ process v
494
+ end
495
+ end
496
+
497
+ sexp
498
+ end
499
+
485
500
  ##
486
501
  # Calculate the difference between known methods and called methods.
487
502
 
@@ -520,23 +535,24 @@ class Debride < MethodBasedSexpProcessor
520
535
  def missing_locations
521
536
  focus = option[:focus]
522
537
 
523
- missing.map { |klass, meths|
524
- bad = meths.map { |meth|
525
- location =
526
- method_locations["#{klass}##{meth}"] ||
527
- method_locations["#{klass}::#{meth}"]
538
+ missing
539
+ .map { |klass, meths|
540
+ bad = meths.map { |meth|
541
+ location =
542
+ method_locations["#{klass}##{meth}"] ||
543
+ method_locations["#{klass}::#{meth}"]
528
544
 
529
- if focus then
530
- path = location[/(.+):\d+/, 1]
545
+ if focus then
546
+ path = location[/(.+):\d+/, 1]
531
547
 
532
- next unless File.fnmatch(focus, path)
533
- end
548
+ next unless File.fnmatch(focus, path)
549
+ end
534
550
 
535
- [meth, location]
536
- }.compact
551
+ [meth, location]
552
+ }.compact
537
553
 
538
- [klass, bad]
539
- }
554
+ [klass, bad]
555
+ }
540
556
  .to_h
541
557
  .reject { |k,v| v.empty? }
542
558
  end
data/test/test_debride.rb CHANGED
@@ -20,6 +20,7 @@ class TestDebride < Minitest::Test
20
20
  :process_const,
21
21
  :process_defn,
22
22
  :process_defs,
23
+ :process_hash,
23
24
  :process_op_asgn2,
24
25
  :process_rb,
25
26
  :process_safe_call,
@@ -46,13 +47,15 @@ class TestDebride < Minitest::Test
46
47
  assert_equal exp_arg, arg
47
48
  end
48
49
 
49
- def assert_process exp, ruby, opts = {}
50
+ def assert_process exp, ruby, called:nil, **opts
50
51
  io = StringIO.new ruby
51
52
 
52
53
  debride = Debride.new opts
53
54
  debride.process debride.process_rb io
54
55
 
55
56
  assert_equal exp, debride.missing
57
+ assert_equal Set[*called], debride.called if called
58
+
56
59
  debride
57
60
  end
58
61
 
@@ -240,6 +243,40 @@ class TestDebride < Minitest::Test
240
243
  assert_process [], s
241
244
  end
242
245
 
246
+ def test_call__alias_method__symbol
247
+ ruby = <<~'RUBY'
248
+ class QuarterPounder
249
+ alias_method :get_x, :x
250
+ end
251
+ RUBY
252
+
253
+ exp = [["QuarterPounder", [:get_x]]]
254
+
255
+ assert_process exp, ruby, called:%i[x alias_method]
256
+ end
257
+
258
+ def test_call__alias_method__string
259
+ ruby = <<~'RUBY'
260
+ class QuarterPounder
261
+ alias_method "get_x", "x"
262
+ end
263
+ RUBY
264
+
265
+ exp = [["QuarterPounder", [:get_x]]]
266
+
267
+ assert_process exp, ruby, called:%i[x alias_method]
268
+ end
269
+
270
+ def test_call__alias_method__interpolated
271
+ ruby = <<~'RUBY'
272
+ class QuarterPounder
273
+ alias_method "get_#{integr}", integr
274
+ end
275
+ RUBY
276
+
277
+ assert_process [], ruby, called:%i[integr alias_method]
278
+ end
279
+
243
280
  def test_alias_method_chain
244
281
  ruby = <<-RUBY.strip
245
282
  class QuarterPounder
@@ -352,6 +389,42 @@ class TestDebride < Minitest::Test
352
389
  assert_process [], ruby
353
390
  end
354
391
 
392
+ def test_hash__shorthand
393
+ ruby = <<-RUBY.strip
394
+ class Seattle
395
+ def self.status
396
+ { raining: }
397
+ end
398
+
399
+ def self.raining
400
+ true
401
+ end
402
+ end
403
+
404
+ Seattle.status
405
+ RUBY
406
+
407
+ assert_process [], ruby
408
+ end
409
+
410
+ def test_hash__not_shorthand
411
+ ruby = <<-RUBY.strip
412
+ class Seattle
413
+ def self.status
414
+ { missing: }
415
+ end
416
+
417
+ def self.raining
418
+ true
419
+ end
420
+ end
421
+
422
+ Seattle.status
423
+ RUBY
424
+
425
+ assert_process [["Seattle", [:raining]]], ruby
426
+ end
427
+
355
428
  def test_safe_navigation_operator
356
429
  ruby = <<-RUBY.strip
357
430
  class Seattle
@@ -412,7 +485,7 @@ class TestDebride < Minitest::Test
412
485
  end
413
486
 
414
487
  def test_rails_dsl_macro_definitions
415
- ruby = <<-RUBY.strip
488
+ ruby = <<~'RUBY'
416
489
  class RailsModel
417
490
  has_one :has_one_relation
418
491
  has_one :uncalled_has_one_relation
@@ -424,6 +497,9 @@ class TestDebride < Minitest::Test
424
497
  has_and_belongs_to_many :uncalled_has_and_belongs_to_many_relation
425
498
  scope :scope_method
426
499
  scope :uncalled_scope_method
500
+ scope :"interpolated_#{method}"
501
+ scope "another_#{method}"
502
+ scope "yet_another_#{method}".to_sym
427
503
 
428
504
  def instance_method_caller
429
505
  has_one_relation
data.tar.gz.sig CHANGED
@@ -1,4 +1,4 @@
1
- ��Y�=n���vRvN�-4~����n�����Q6����R�;��Tځ̿��\�Q��Lը�E�Ÿ�<*�Ԑ�7JU�Q��kHc��ץ�\����*3��c�/�
2
- ��ݐm m2�}|6 1�����}-MC�g��`F��P*���
3
- I��€Fގ<� QK�E��L��nۗێ��m �ta���LI:
4
- -T���o���<��fRLSUqg��? T>�P~F���QD�Z|����lz�+�?�H�
1
+ b����k�$���i���~�
2
+ �>�p��h[��
3
+ �ۯ�7~��\V?�*[~���� ٕ�)�^$[��I7 3�E}Q(�k�So����S��w^ �-&�ɧrr ѓGV�����]�+ ���(0vq��WJȻC4��軺?��o?�BBP�u�p�G^.���D@��o��q4�Χ�P!��5�w5�� c?�B��?O?�ᐟ�W�
4
+ �c�m9��qw/)֛L(W
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: debride
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.0
4
+ version: 1.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Davis
@@ -9,9 +9,9 @@ bindir: bin
9
9
  cert_chain:
10
10
  - |
11
11
  -----BEGIN CERTIFICATE-----
12
- MIIDPjCCAiagAwIBAgIBCTANBgkqhkiG9w0BAQsFADBFMRMwEQYDVQQDDApyeWFu
12
+ MIIDPjCCAiagAwIBAgIBCjANBgkqhkiG9w0BAQsFADBFMRMwEQYDVQQDDApyeWFu
13
13
  ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
14
- GRYDY29tMB4XDTI1MDEwNjIzMjcwMVoXDTI2MDEwNjIzMjcwMVowRTETMBEGA1UE
14
+ GRYDY29tMB4XDTI2MDEwNzAxMDkxNFoXDTI3MDEwNzAxMDkxNFowRTETMBEGA1UE
15
15
  AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
16
16
  JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
17
17
  b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
@@ -21,12 +21,12 @@ cert_chain:
21
21
  qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
22
22
  gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
23
23
  HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBCwUAA4IB
24
- AQAC0WQJcPOWPFwkojhzweilRVjTJ19UiLhiBTw3C1wJO3LVdBkWDmnnhAmKuX4D
25
- r7vjQvESlABGIPdutI1Yl7mrHQzTkfLfXvNN6MT0nLChPyIYauT6SZZxubwJrUfA
26
- 7R0c2CJTIboZ0XaGpLsXqHEF1c29H7TV1QvVuqKAN2mCjh4N82QVn+ZKtys28AwT
27
- 6GfQX2fqLoi4KSc7xIzHKaNzqxeOICmJofk9w5VZ2rRN6yes8jvFYwz9HR41wdj8
28
- bwfinv7Yp5fA6AysuZLhCykyfDuZVRrUp0Vb68YCKsLjJly/Theak+euNTxvHsB+
29
- al9oSgPPHICMEX65qvLywitx
24
+ AQA/X8/PKTTc/IkYQEUL6XWtfK8fAfbuLJzmLcz6f2ZWrtBvPsYvqRuwI1bWUtil
25
+ 2ibJEfIuSIHX6BsUTX18+hlaIussf6EWq/YkE7e2BKmgQE42vSOZMce0kCEAPbx0
26
+ rQtqonfWTHQ8UbQ7GqCL3gDQ0QDD2B+HUlb4uaCZ2icxqa/eOtxMvHC2tj+h0xKY
27
+ xL84ipM5kr0bHGf9/MRZJWcw51urueNycBXu1Xh+pEN8qBmYsFRR4SIODLClybAO
28
+ 6cbm2PyPQgKNiqE4H+IQrDVHd9bJs1XgLElk3qoaJBWXc/5fy0J1imYb25UqmiHG
29
+ snGe1hrppvBRdcyEzvhfIPjI
30
30
  -----END CERTIFICATE-----
31
31
  date: 1980-01-02 00:00:00.000000000 Z
32
32
  dependencies:
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.5'
53
+ version: '1.7'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '1.5'
60
+ version: '1.7'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: path_expander
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -78,20 +78,20 @@ dependencies:
78
78
  requirements:
79
79
  - - ">="
80
80
  - !ruby/object:Gem::Version
81
- version: '4.0'
81
+ version: '6.0'
82
82
  - - "<"
83
83
  - !ruby/object:Gem::Version
84
- version: '7'
84
+ version: '8'
85
85
  type: :development
86
86
  prerelease: false
87
87
  version_requirements: !ruby/object:Gem::Requirement
88
88
  requirements:
89
89
  - - ">="
90
90
  - !ruby/object:Gem::Version
91
- version: '4.0'
91
+ version: '6.0'
92
92
  - - "<"
93
93
  - !ruby/object:Gem::Version
94
- version: '7'
94
+ version: '8'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: simplecov
97
97
  requirement: !ruby/object:Gem::Requirement
@@ -112,14 +112,14 @@ dependencies:
112
112
  requirements:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '4.3'
115
+ version: '4.5'
116
116
  type: :development
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
119
119
  requirements:
120
120
  - - "~>"
121
121
  - !ruby/object:Gem::Version
122
- version: '4.3'
122
+ version: '4.5'
123
123
  description: Analyze code for potentially uncalled / dead methods, now with auto-removal.
124
124
  email:
125
125
  - ryand-ruby@zenspider.com
metadata.gz.sig CHANGED
Binary file