debride 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a723b84c9a06468449e24ec4cf6f8911f1cfbc1
4
- data.tar.gz: 7a135fd947b6cbd2905f4d4196aa526966f465e6
3
+ metadata.gz: a6fb60e6abb914cdca253c8f91a87ee9f29b9573
4
+ data.tar.gz: c277e27c75a4a571e22cc647fe4d98063f944256
5
5
  SHA512:
6
- metadata.gz: 6b43c1951aac3602c0ec3bbf1bb28e9aa14d976bb6cc4af7073000795dea551e78d58a20b924396cb2e09f5d422eb9af519d394b413964c541a17ddc46d23ac0
7
- data.tar.gz: eae873a00409532767de144cea3d1f31249d4083a0823bb96ee38f89db7f4321bd4cbf54a977e4b494a55c4b66f531674a22f98bafdae7e51dbb1220207a7997
6
+ metadata.gz: dc8279ae3e71097d6b57ade1054d80c596b76e6b47878b8269fd931abca6b497da3780cf85cff3860563b307a2c01f727fe11f1bc03a11287242e3bd376c75d7
7
+ data.tar.gz: 560722e6f9d07d1dff4bab14e912cec2d9a019046ee4a5dcfc7a6394e98c9f933e0ff1c4c9dc9b85f2cdd1ad2093889acd2926fb05246bfc96c3bd89bbf477a7
Binary file
data.tar.gz.sig CHANGED
Binary file
data/.autotest CHANGED
@@ -1,6 +1,7 @@
1
1
  # -*- ruby -*-
2
2
 
3
3
  require "autotest/restart"
4
+ require "autotest/isolate"
4
5
 
5
6
  Autotest.add_hook :initialize do |at|
6
7
  at.testlib = "minitest/autorun"
@@ -1,3 +1,21 @@
1
+ === 1.4.0 / 2015-05-27
2
+
3
+ * 1 major enhancement:
4
+
5
+ * Added support for analyzing potentially unused constants.
6
+
7
+ * 5 minor enhancements:
8
+
9
+ * Extended process_rb to work with IO/StringIO.
10
+ * Print file being processed if --verbose.
11
+ * Print help and exit if no files/dirs specified. (phiggins)
12
+ * Rescue RubyParser parse errors, warn, and skip.
13
+ * Use RubyParser.for_current_ruby.
14
+
15
+ * 1 bug fix:
16
+
17
+ * Debride.new will default to proper options.
18
+
1
19
  === 1.3.0 / 2015-04-13
2
20
 
3
21
  * 4 minor enhancements:
@@ -38,6 +38,11 @@ API), then you can whitelist it:
38
38
 
39
39
  You can also use regexps in your whitelist by delimiting them with //'s.
40
40
 
41
+ == PLUGINS:
42
+
43
+ debride-erb :: Extends debride to analyze erb files (via erubis ala rails).
44
+ debride-haml :: Plugin to allow debride to parse Haml files.
45
+
41
46
  == REQUIREMENTS:
42
47
 
43
48
  * ruby 1.8+
data/Rakefile CHANGED
@@ -15,10 +15,28 @@ Hoe.spec "debride" do
15
15
  dependency "ruby_parser", "~> 3.6"
16
16
  end
17
17
 
18
- task :rails do
18
+ def run dir, wl
19
19
  ENV["GEM_HOME"] = "tmp/isolate/ruby-2.0.0"
20
20
  ENV["GEM_PATH"] = "../../debride-erb/dev/tmp/isolate/ruby-2.0.0"
21
- ruby "-Ilib:../../debride-erb/dev/lib bin/debride --rails ~/Work/git/seattlerb.org/{app,lib} --whitelist ~/Work/git/seattlerb.org/whitelist.txt"
21
+
22
+ abort "Specify dir to scan with D=<path>" unless dir
23
+ wl = "--whitelist #{wl}" if wl
24
+
25
+ ruby "-Ilib:../../debride-erb/dev/lib bin/debride --rails #{dir} #{wl}"
26
+ end
27
+
28
+ task :run do
29
+ run ENV["D"], ENV["W"]
30
+ end
31
+
32
+ task :rails do
33
+ d = "~/Work/git/seattlerb.org"
34
+ run "#{d}/{app,lib,config}", "#{d}/whitelist.txt"
35
+ end
36
+
37
+ task :debug do
38
+ f = ENV["F"]
39
+ run f, nil
22
40
  end
23
41
 
24
42
  # vim: syntax=ruby
@@ -5,11 +5,21 @@ require "sexp_processor"
5
5
  require "optparse"
6
6
  require "set"
7
7
 
8
+ # :stopdoc:
9
+ class File
10
+ RUBY19 = "<3".respond_to? :encoding unless defined? RUBY19 # :nodoc:
11
+
12
+ class << self
13
+ alias :binread :read unless RUBY19
14
+ end
15
+ end
16
+ # :startdoc:
17
+
8
18
  ##
9
19
  # A static code analyzer that points out possible dead methods.
10
20
 
11
21
  class Debride < MethodBasedSexpProcessor
12
- VERSION = "1.3.0" # :nodoc:
22
+ VERSION = "1.4.0" # :nodoc:
13
23
  PROJECT = "debride"
14
24
 
15
25
  def self.expand_dirs_to_files *dirs # TODO: push back up to sexp_processor
@@ -88,11 +98,25 @@ class Debride < MethodBasedSexpProcessor
88
98
  end
89
99
  end
90
100
 
91
- def process_rb file
101
+ def process_rb path_or_io
92
102
  begin
93
- RubyParser.new.process(File.binread(file), file, option[:timeout])
103
+ warn "processing: #{path}" if option[:verbose]
104
+
105
+ case path_or_io
106
+ when String then
107
+ path, file = path_or_io, File.binread(path_or_io)
108
+ when IO, StringIO then
109
+ path, file = "(io)", path_or_io.read
110
+ else
111
+ raise "Unhandled type: #{path_or_io.class}:#{path_or_io.inspect}"
112
+ end
113
+
114
+ RubyParser.for_current_ruby.process(file, path, option[:timeout])
115
+ rescue Racc::ParseError => e
116
+ warn "Parse Error parsing #{path}. Skipping."
117
+ warn " #{e.message}"
94
118
  rescue Timeout::Error
95
- warn "TIMEOUT parsing #{file}. Skipping."
119
+ warn "TIMEOUT parsing #{path}. Skipping."
96
120
  end
97
121
  end
98
122
 
@@ -102,7 +126,7 @@ class Debride < MethodBasedSexpProcessor
102
126
  def self.parse_options args
103
127
  options = {:whitelist => []}
104
128
 
105
- OptionParser.new do |opts|
129
+ op = OptionParser.new do |opts|
106
130
  opts.banner = "debride [options] files_or_dirs"
107
131
  opts.version = Debride::VERSION
108
132
 
@@ -134,6 +158,8 @@ class Debride < MethodBasedSexpProcessor
134
158
  opts.parse! args
135
159
  end
136
160
 
161
+ abort op.to_s if args.empty?
162
+
137
163
  options
138
164
  end
139
165
 
@@ -157,7 +183,7 @@ class Debride < MethodBasedSexpProcessor
157
183
  # Create a new Debride instance w/ +options+
158
184
 
159
185
  def initialize options = {}
160
- self.option = options
186
+ self.option = { :whitelist => [] }.merge options
161
187
  self.known = Hash.new { |h,k| h[k] = Set.new }
162
188
  self.called = Set.new
163
189
  self.map = Hash.new { |h,k| h[k] = {} }
@@ -172,6 +198,41 @@ class Debride < MethodBasedSexpProcessor
172
198
  super.to_s.sub(/^::|#/, "").to_sym
173
199
  end
174
200
 
201
+ def process_cdecl exp # :nodoc:
202
+ _, name, val = exp
203
+ process val
204
+
205
+ map[klass_name][name] = "#{klass_name}::#{name}"
206
+ known[name] << klass_name
207
+
208
+ exp
209
+ end
210
+
211
+ def process_colon2 exp # :nodoc:
212
+ _, lhs, name = exp
213
+ process lhs
214
+
215
+ called << name
216
+
217
+ exp
218
+ end
219
+
220
+ def process_colon3 exp # :nodoc:
221
+ _, name = exp
222
+
223
+ called << name
224
+
225
+ exp
226
+ end
227
+
228
+ def process_const exp # :nodoc:
229
+ _, name = exp
230
+
231
+ called << name
232
+
233
+ exp
234
+ end
235
+
175
236
  def process_defn sexp # :nodoc:
176
237
  super do
177
238
  map[klass_name][method_name] = signature
@@ -256,7 +317,7 @@ class Debride < MethodBasedSexpProcessor
256
317
 
257
318
  whitelist_regexp = Regexp.union whitelist_regexps
258
319
 
259
- not_called.reject! { |s| whitelist_regexp =~ s }
320
+ not_called.reject! { |s| whitelist_regexp =~ s.to_s }
260
321
 
261
322
  by_class = Hash.new { |h,k| h[k] = [] }
262
323
 
@@ -1,8 +1,33 @@
1
1
  require "minitest/autorun"
2
2
  require "debride"
3
3
 
4
+ class SafeDebride < Debride
5
+ def self.abort s
6
+ raise s
7
+ end
8
+ end
9
+
4
10
  class TestDebride < Minitest::Test
11
+ def assert_option arg, exp_arg, exp_opt
12
+ opt = SafeDebride.parse_options arg
13
+
14
+ exp_opt = {:whitelist => []}.merge exp_opt
15
+ assert_equal exp_opt, opt
16
+ assert_equal exp_arg, arg
17
+ end
18
+
19
+ def assert_process exp, ruby, opts = {}
20
+ io = StringIO.new ruby
21
+
22
+ debride = Debride.new opts
23
+ debride.process debride.process_rb io
24
+
25
+ assert_equal exp, debride.missing
26
+ end
27
+
5
28
  def test_sanity
29
+ skip "This is slow" unless ENV["SLOW"]
30
+
6
31
  debride = nil
7
32
 
8
33
  assert_silent do
@@ -15,34 +40,39 @@ class TestDebride < Minitest::Test
15
40
  assert_equal exp, debride.missing
16
41
  end
17
42
 
18
- def assert_option arg, rest, exp_opt
19
- opt = Debride.parse_options arg
20
-
21
- exp_opt = {:whitelist => []}.merge exp_opt
22
- assert_equal exp_opt, opt
23
- assert_equal rest, arg
43
+ def test_parse_options
44
+ assert_option %w[--verbose woot.rb], %w[woot.rb], :verbose => true
45
+ assert_option %w[-v woot.rb], %w[woot.rb], :verbose => true
24
46
  end
25
47
 
26
- def test_parse_options
27
- assert_option %w[], %w[], {}
48
+ def test_parse_options_empty
49
+ e = assert_raises RuntimeError do
50
+ assert_option %w[], %w[], {}
51
+ end
52
+
53
+ assert_includes e.message, "debride [options] files_or_dirs"
28
54
 
29
- assert_option %w[--verbose], %w[], :verbose => true
30
- assert_option %w[-v], %w[], :verbose => true
31
- assert_option %w[-v woot.rb], %w[woot.rb], :verbose => true
55
+ e = assert_raises RuntimeError do
56
+ assert_option %w[-v], %w[], :verbose => true
57
+ end
58
+
59
+ assert_includes e.message, "debride [options] files_or_dirs"
32
60
  end
33
61
 
34
62
  def test_parse_options_exclude
35
- assert_option %w[--exclude moot.rb], %w[], :exclude => %w[moot.rb]
36
- assert_option %w[-e moot lib], %w[lib], :exclude => %w[moot]
37
- assert_option %w[-e moot,moot.rb lib], %w[lib], :exclude => %w[moot moot.rb]
63
+ assert_option %w[--exclude moot.rb lib], %w[lib], :exclude => %w[moot.rb]
64
+ assert_option %w[-e moot lib], %w[lib], :exclude => %w[moot]
65
+ assert_option %w[-e moot,moot.rb lib], %w[lib], :exclude => %w[moot moot.rb]
38
66
  end
39
67
 
40
68
  def test_parse_options_whitelist
41
69
  exp = File.readlines("Manifest.txt").map(&:chomp) # omg dumb
42
- assert_option %w[--whitelist Manifest.txt], %w[], :whitelist => exp
70
+ assert_option %w[--whitelist Manifest.txt lib], %w[lib], :whitelist => exp
43
71
  end
44
72
 
45
73
  def test_exclude_files
74
+ skip "This is slow" unless ENV["SLOW"]
75
+
46
76
  debride = Debride.run %w[--exclude test lib]
47
77
 
48
78
  exp = [["Debride",
@@ -52,28 +82,80 @@ class TestDebride < Minitest::Test
52
82
  end
53
83
 
54
84
  def test_whitelist
55
- debride = Debride.run %w[lib]
56
- debride.option[:whitelist] = %w[process_defn]
85
+ ruby = <<-RUBY
86
+ class Seattle
87
+ def self.raining?
88
+ true
89
+ end
90
+ end
57
91
 
58
- exp = [["Debride",
59
- [:process_call, :process_defs, :process_rb, :report]]]
92
+ # Seattle.raining?
93
+ RUBY
60
94
 
61
- assert_equal exp, debride.missing
95
+ exp = [["Seattle", [:raining?]]]
96
+ assert_process exp, ruby
97
+
98
+ exp = []
99
+ assert_process exp, ruby, :whitelist => %w[raining?]
62
100
  end
63
101
 
64
102
  def test_whitelist_regexp
65
- debride = Debride.run %w[lib]
66
- debride.option[:whitelist] = %w[/^process_/ run]
103
+ ruby = <<-RUBY
104
+ class Seattle
105
+ def self.raining?
106
+ true
107
+ end
108
+ end
67
109
 
68
- exp = [["Debride", [:report]]]
110
+ # Seattle.raining?
111
+ RUBY
69
112
 
70
- assert_equal exp, debride.missing
113
+ exp = [["Seattle", [:raining?]]]
114
+ assert_process exp, ruby
115
+
116
+ exp = []
117
+ assert_process exp, ruby, :whitelist => %w[/raining/]
71
118
  end
72
119
 
73
- def test_alias_method_chain
120
+ def test_process_rb_path
74
121
  file = Tempfile.new ["debride_test", ".rb"]
75
122
 
76
123
  file.write <<-RUBY.strip
124
+ class Seattle
125
+ def self.raining?
126
+ true
127
+ end
128
+ end
129
+
130
+ Seattle.raining?
131
+ RUBY
132
+
133
+ file.flush
134
+
135
+ debride = Debride.new
136
+ debride.process_rb file.path
137
+
138
+ exp = []
139
+
140
+ assert_equal exp, debride.missing
141
+ end
142
+
143
+ def test_process_rb_io
144
+ s = <<-RUBY.strip
145
+ class Seattle
146
+ def self.raining?
147
+ true
148
+ end
149
+ end
150
+
151
+ Seattle.raining?
152
+ RUBY
153
+
154
+ assert_process [], s
155
+ end
156
+
157
+ def test_alias_method_chain
158
+ ruby = <<-RUBY.strip
77
159
  class QuarterPounder
78
160
  def royale_with_cheese
79
161
  1+1
@@ -83,19 +165,13 @@ class TestDebride < Minitest::Test
83
165
  end
84
166
  RUBY
85
167
 
86
- file.flush
87
-
88
- debride = Debride.run [file.path, "--rails"]
89
-
90
168
  exp = [["QuarterPounder", [:royale, :royale_with_cheese]]]
91
169
 
92
- assert_equal exp, debride.missing
170
+ assert_process exp, ruby, :rails => true
93
171
  end
94
172
 
95
173
  def test_method_send
96
- file = Tempfile.new ["debride_test", ".rb"]
97
-
98
- file.write <<-RUBY.strip
174
+ ruby = <<-RUBY.strip
99
175
  class Seattle
100
176
  def self.raining?
101
177
  true
@@ -111,19 +187,11 @@ class TestDebride < Minitest::Test
111
187
  Seattle.send "\#{foo}_bar"
112
188
  RUBY
113
189
 
114
- file.flush
115
-
116
- debride = Debride.run [file.path]
117
-
118
- exp = []
119
-
120
- assert_equal exp, debride.missing
190
+ assert_process [], ruby
121
191
  end
122
192
 
123
193
  def test_rails_dsl_methods
124
- file = Tempfile.new ["debride_test", ".rb"]
125
-
126
- file.write <<-RUBY.strip
194
+ ruby = <<-RUBY.strip
127
195
  class RailsThing
128
196
  def save_callback ; 1 ; end
129
197
  def action_filter ; 1 ; end
@@ -140,10 +208,26 @@ class TestDebride < Minitest::Test
140
208
  end
141
209
  RUBY
142
210
 
143
- file.flush
211
+ assert_process [], ruby, :rails => true
212
+ end
144
213
 
145
- debride = Debride.run [file.path, "--rails"]
214
+ def test_constants
215
+ ruby = <<-RUBY.strip
216
+ class Constants
217
+ USED = 42
218
+ ALSO = 314
219
+ UNUSED = 24
220
+
221
+ def something
222
+ p USED
223
+ end
224
+ end
225
+
226
+ something
227
+ Constants::ALSO
228
+ ::Constants::ALSO
229
+ RUBY
146
230
 
147
- assert_equal [], debride.missing.sort
231
+ assert_process [["Constants", [:UNUSED]]], ruby
148
232
  end
149
233
  end
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.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Davis
@@ -29,7 +29,7 @@ cert_chain:
29
29
  xJcC6UN6NHMOVMyAXsr2HR0gRRx4ofN1LoP2KhXzSr8UMvQYlwPmE0N5GQv1b5AO
30
30
  VpzF30vNaJK6ZT7xlIsIlwmH
31
31
  -----END CERTIFICATE-----
32
- date: 2015-04-13 00:00:00.000000000 Z
32
+ date: 2015-05-27 00:00:00.000000000 Z
33
33
  dependencies:
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: sexp_processor
metadata.gz.sig CHANGED
@@ -1 +1 @@
1
- i�y��`2æ;kd葅��*�籃�W�O��)���/s�5�g�6�=�qbwb]E*���c)μ� VRƼE״����|~�0&�ͦ�ʮ�W��H3Z�yh��0βs�F35»c�̦ϕ_L6֜�|��r��S ���)X3B}*N��6��M(a���휹�dQ�℀Ik���L%��uBKҀ���~NHz�󺣞�c�D(���?������g�C���S�P�#>80�NOH�B�V�K����-xl��
1
+ ��S��m=X��?t]���<�8R�I��BKC?ʓ�g����ʯ���1