flay 2.4.0 → 2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a86b433cd154d84be7076b6172db4ef1cc399472
4
+ data.tar.gz: d5443415472f22efc31f9fc91c5c40d144f8aedc
5
+ SHA512:
6
+ metadata.gz: d258e0487193665da980125c5245ed86415dfdaf4f51f4453044a3e851d0ee619ddf65a607debd07f4f7cd48af0d62697556c53620aa4060de5ce91be806c320
7
+ data.tar.gz: e578e44ec8118ce4e3dac841910356ed5e344259f47dd08c094734a2d8a1676c4ba2d04b2e9fbf391371ad7ddefc9f5602391b343722f50fc7c2e688ec8ccfe3
checksums.yaml.gz.sig ADDED
@@ -0,0 +1 @@
1
+ q}���y`��)s I� �f�ٟw�n��T ƍW�$�%�M�w�/]x�� �Ԗ�q�o�
data.tar.gz.sig CHANGED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,14 @@
1
+ === 2.5.0 / 2014-05-29
2
+
3
+ * 6 minor enhancements:
4
+
5
+ * Added Flay::Item and Flay::Location to encapsulate analysis.
6
+ * Added `--only nodetype` filter flag.
7
+ * Flay#analyze now returns a nice data structure you can walk over.
8
+ * Flay#report is now much more dumb. :)
9
+ * Flay#report now takes an optional IO object.
10
+ * Removed unused prune arg in Flay#report.
11
+
1
12
  === 2.4.0 / 2013-07-24
2
13
 
3
14
  * 1 minor enhancement:
data/README.txt CHANGED
@@ -30,6 +30,7 @@ braces vs do/end, etc are all ignored. Making this totally rad.
30
30
  == KNOWN EXTENSIONS:
31
31
 
32
32
  * flay-actionpack :: Use Rails ERB handler.
33
+ * flay-js :: Process JavaScript files.
33
34
  * flay-haml :: Flay your HAML source.
34
35
  * flay-persistence :: Persist results across runs. Great for multi-project analysis.
35
36
 
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- ruby -*-
2
2
 
3
- require 'rubygems'
4
- require 'hoe'
3
+ require "rubygems"
4
+ require "hoe"
5
5
 
6
6
  Hoe::add_include_dirs("../../sexp_processor/dev/lib",
7
7
  "../../ruby_parser/dev/lib",
@@ -11,14 +11,14 @@ Hoe::add_include_dirs("../../sexp_processor/dev/lib",
11
11
 
12
12
  Hoe.plugin :seattlerb
13
13
 
14
- Hoe.spec 'flay' do
15
- developer 'Ryan Davis', 'ryand-ruby@zenspider.com'
14
+ Hoe.spec "flay" do
15
+ developer "Ryan Davis", "ryand-ruby@zenspider.com"
16
+ license "MIT"
16
17
 
17
- self.rubyforge_name = 'seattlerb'
18
- self.flay_threshold = 250
18
+ dependency "sexp_processor", "~> 4.0"
19
+ dependency "ruby_parser", "~> 3.0"
19
20
 
20
- dependency 'sexp_processor', '~> 4.0'
21
- dependency 'ruby_parser', '~> 3.0'
21
+ self.flay_threshold = 250
22
22
  end
23
23
 
24
24
  task :debug do
data/lib/flay.rb CHANGED
@@ -15,7 +15,15 @@ class File
15
15
  end
16
16
 
17
17
  class Flay
18
- VERSION = "2.4.0" # :nodoc:
18
+ VERSION = "2.5.0" # :nodoc:
19
+
20
+ class Item < Struct.new(:structural_hash, :name, :bonus, :mass, :locations)
21
+ alias identical? bonus
22
+ end
23
+
24
+ class Location < Struct.new(:file, :line, :fuzzy)
25
+ alias fuzzy? fuzzy
26
+ end
19
27
 
20
28
  ##
21
29
  # Returns the default options.
@@ -30,6 +38,7 @@ class Flay
30
38
  :timeout => 10,
31
39
  :liberal => false,
32
40
  :fuzzy => false,
41
+ :only => nil,
33
42
  }
34
43
  end
35
44
 
@@ -74,6 +83,10 @@ class Flay
74
83
  options[:verbose] = true
75
84
  end
76
85
 
86
+ opts.on('-o', '--only NODE', String, "Only show matches on NODE type.") do |s|
87
+ options[:only] = s.to_sym
88
+ end
89
+
77
90
  opts.on('-d', '--diff', "Diff Mode. Display N-Way diff for ruby.") do
78
91
  options[:diff] = true
79
92
  end
@@ -204,7 +217,7 @@ class Flay
204
217
  ##
205
218
  # Prune, find identical nodes, and update masses.
206
219
 
207
- def analyze
220
+ def analyze filter = nil
208
221
  self.prune
209
222
 
210
223
  self.hashes.each do |hash,nodes|
@@ -212,6 +225,31 @@ class Flay
212
225
  end
213
226
 
214
227
  update_masses
228
+
229
+ sorted = masses.sort_by { |h,m|
230
+ [-m,
231
+ hashes[h].first.file,
232
+ hashes[h].first.line,
233
+ hashes[h].first.first.to_s]
234
+ }
235
+
236
+ sorted.map { |hash, mass|
237
+ nodes = hashes[hash]
238
+
239
+ next unless nodes.first.first == filter if filter
240
+
241
+ same = identical[hash]
242
+ node = nodes.first
243
+ n = nodes.size
244
+ bonus = "*#{n}" if same
245
+
246
+ locs = nodes.sort_by { |x| [x.file, x.line] }.each_with_index.map { |x, i|
247
+ extra = :fuzzy if x.modified?
248
+ Location[x.file, x.line, extra]
249
+ }
250
+
251
+ Item[hash, node.first, bonus, mass, locs]
252
+ }.compact
215
253
  end
216
254
 
217
255
  ##
@@ -427,70 +465,49 @@ class Flay
427
465
  ##
428
466
  # Output the report. Duh.
429
467
 
430
- def report prune = nil
431
- analyze
468
+ def report io = $stdout
469
+ only = option[:only]
470
+
471
+ data = analyze only
432
472
 
433
- puts "Total score (lower is better) = #{self.total}"
473
+ io.puts "Total score (lower is better) = #{self.total}"
434
474
 
435
475
  if option[:summary] then
436
- puts
476
+ io.puts
437
477
 
438
478
  self.summary.sort_by { |_,v| -v }.each do |file, score|
439
- puts "%8.2f: %s" % [score, file]
479
+ io.puts "%8.2f: %s" % [score, file]
440
480
  end
441
481
 
442
482
  return
443
483
  end
444
484
 
445
- count = 0
446
- sorted = masses.sort_by { |h,m|
447
- [-m,
448
- hashes[h].first.file,
449
- hashes[h].first.line,
450
- hashes[h].first.first.to_s]
451
- }
452
- sorted.each do |hash, mass|
453
- nodes = hashes[hash]
454
- next unless nodes.first.first == prune if prune
455
- puts
456
-
457
- same = identical[hash]
458
- node = nodes.first
459
- n = nodes.size
460
- match, bonus = if same then
461
- ["IDENTICAL", "*#{n}"]
462
- else
463
- ["Similar", ""]
464
- end
465
-
466
- if option[:number] then
467
- count += 1
468
-
469
- puts "%d) %s code found in %p (mass%s = %d)" %
470
- [count, match, node.first, bonus, mass]
471
- else
472
- puts "%s code found in %p (mass%s = %d)" %
473
- [match, node.first, bonus, mass]
474
- end
485
+ data.each_with_index do |item, count|
486
+ prefix = "%d) " % (count + 1) if option[:number]
475
487
 
476
- nodes.sort_by { |x| [x.file, x.line] }.each_with_index do |x, i|
477
- if option[:diff] then
478
- c = (?A.ord + i).chr
479
- extra = " (FUZZY)" if x.modified?
480
- puts " #{c}: #{x.file}:#{x.line}#{extra}"
481
- else
482
- extra = " (FUZZY)" if x.modified?
483
- puts " #{x.file}:#{x.line}#{extra}"
484
- end
488
+ match = item.identical? ? "IDENTICAL" : "Similar"
489
+
490
+ io.puts
491
+ io.puts "%s%s code found in %p (mass%s = %d)" %
492
+ [prefix, match, item.name, item.bonus, item.mass]
493
+
494
+ item.locations.each_with_index do |loc, i|
495
+ loc_prefix = "%s: " % (?A.ord + i).chr if option[:diff]
496
+ extra = " (FUZZY)" if loc.fuzzy?
497
+ io.puts " %s%s:%d%s" % [loc_prefix, loc.file, loc.line, extra]
485
498
  end
486
499
 
487
500
  if option[:diff] then
488
- puts
501
+ io.puts
502
+
503
+ nodes = hashes[item.structural_hash]
504
+
489
505
  sources = nodes.map do |s|
490
506
  msg = "sexp_to_#{File.extname(s.file).sub(/./, '')}"
491
507
  self.respond_to?(msg) ? self.send(msg, s) : sexp_to_rb(s)
492
508
  end
493
- puts n_way_diff(*sources)
509
+
510
+ io.puts n_way_diff(*sources)
494
511
  end
495
512
  end
496
513
  end
data/test/test_flay.rb CHANGED
@@ -20,8 +20,8 @@ class TestSexp < Minitest::Test
20
20
  s(:lasgn),
21
21
  s(:call, s(:arglist))).hash
22
22
 
23
- assert_equal hash, @s.structural_hash
24
23
  assert_equal hash, @s.deep_clone.structural_hash
24
+ assert_equal hash, @s.structural_hash
25
25
  end
26
26
 
27
27
  def test_delete_eql
@@ -208,23 +208,13 @@ class TestSexp < Minitest::Test
208
208
  end
209
209
 
210
210
  def test_report
211
- # make sure we run through options parser
212
- $*.clear
213
- $* << "--mass=1"
214
- $* << "-v"
215
-
216
- opts = nil
217
- capture_io do # ignored
218
- opts = Flay.parse_options
219
- end
220
-
221
- flay = Flay.new opts
211
+ flay = Flay.new Flay.parse_options %w[--mass=1 -v]
222
212
 
223
213
  flay.process_sexp DOG_AND_CAT.deep_clone
224
214
  flay.analyze
225
215
 
226
216
  out, err = capture_io do
227
- flay.report nil
217
+ flay.report
228
218
  end
229
219
 
230
220
  exp = <<-END.gsub(/\d+/, "N").gsub(/^ {6}/, "")
@@ -239,25 +229,33 @@ class TestSexp < Minitest::Test
239
229
  assert_equal exp, out.gsub(/\d+/, "N")
240
230
  end
241
231
 
242
- def test_report_diff
243
- # make sure we run through options parser
244
- $*.clear
245
- $* << "-d"
246
- $* << "--mass=1"
247
- $* << "-v"
248
-
249
- opts = nil
250
- capture_io do # ignored
251
- opts = Flay.parse_options
252
- end
232
+ def test_report_io
233
+ out = StringIO.new
234
+ flay = Flay.new Flay.parse_options %w[--mass=1 -v]
253
235
 
254
- flay = Flay.new opts
236
+ flay.process_sexp DOG_AND_CAT.deep_clone
237
+ flay.analyze
238
+ flay.report out
239
+
240
+ exp = <<-END.gsub(/\d+/, "N").gsub(/^ {6}/, "")
241
+ Total score (lower is better) = 16
242
+
243
+ 1) Similar code found in :class (mass = 16)
244
+ (string):1
245
+ (string):6
246
+ END
247
+
248
+ assert_equal exp, out.string.gsub(/\d+/, "N")
249
+ end
250
+
251
+ def test_report_diff
252
+ flay = Flay.new Flay.parse_options %w[-d --mass=1 -v]
255
253
 
256
254
  flay.process_sexp DOG_AND_CAT.deep_clone
257
255
  flay.analyze
258
256
 
259
257
  out, err = capture_io do
260
- flay.report nil
258
+ flay.report
261
259
  end
262
260
 
263
261
  exp = <<-END.gsub(/\d+/, "N").gsub(/^ {6}/, "")
@@ -288,18 +286,7 @@ class TestSexp < Minitest::Test
288
286
  end
289
287
 
290
288
  def test_report_diff_plugin_converter
291
- # make sure we run through options parser
292
- $*.clear
293
- $* << "-d"
294
- $* << "--mass=1"
295
- $* << "-v"
296
-
297
- opts = nil
298
- capture_io do # ignored
299
- opts = Flay.parse_options
300
- end
301
-
302
- flay = Flay.new opts
289
+ flay = Flay.new Flay.parse_options %w[-d --mass=1 -v]
303
290
 
304
291
  flay.process_sexp DOG_AND_CAT.deep_clone
305
292
  flay.analyze
@@ -308,7 +295,7 @@ class TestSexp < Minitest::Test
308
295
  Flay.send(:define_method, :sexp_to_){|s| "source code #{s.line}"}
309
296
 
310
297
  out, err = capture_io do
311
- flay.report nil
298
+ flay.report
312
299
  end
313
300
 
314
301
  Flay.send(:remove_method, :sexp_to_)
metadata CHANGED
@@ -1,24 +1,18 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: flay
3
- version: !ruby/object:Gem::Version
4
- hash: 31
5
- prerelease:
6
- segments:
7
- - 2
8
- - 4
9
- - 0
10
- version: 2.4.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.5.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Ryan Davis
14
8
  autorequire:
15
9
  bindir: bin
16
- cert_chain:
10
+ cert_chain:
17
11
  - |
18
12
  -----BEGIN CERTIFICATE-----
19
- MIIDPjCCAiagAwIBAgIBADANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
13
+ MIIDPjCCAiagAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
20
14
  ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
21
- GRYDY29tMB4XDTA5MDMwNjE4NTMxNVoXDTEwMDMwNjE4NTMxNVowRTETMBEGA1UE
15
+ GRYDY29tMB4XDTEzMDkxNjIzMDQxMloXDTE0MDkxNjIzMDQxMlowRTETMBEGA1UE
22
16
  AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
23
17
  JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
24
18
  b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
@@ -28,106 +22,100 @@ cert_chain:
28
22
  qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
29
23
  gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
30
24
  HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBBQUAA4IB
31
- AQAY59gYvDxqSqgC92nAP9P8dnGgfZgLxP237xS6XxFGJSghdz/nI6pusfCWKM8m
32
- vzjjH2wUMSSf3tNudQ3rCGLf2epkcU13/rguI88wO6MrE0wi4ZqLQX+eZQFskJb/
33
- w6x9W1ur8eR01s397LSMexySDBrJOh34cm2AlfKr/jokKCTwcM0OvVZnAutaovC0
34
- l1SVZ0ecg88bsWHA0Yhh7NFxK1utWoIhtB6AFC/+trM0FQEB/jZkIS8SaNzn96Rl
35
- n0sZEf77FLf5peR8TP/PtmIg7Cyqz23sLM4mCOoTGIy5OcZ8TdyiyINUHtb5ej/T
36
- FBHgymkyj/AOSqKRIpXPhjC6
25
+ AQCFZ7JTzoy1gcG4d8A6dmOJy7ygtO5MFpRIz8HuKCF5566nOvpy7aHhDDzFmQuu
26
+ FX3zDU6ghx5cQIueDhf2SGOncyBmmJRRYawm3wI0o1MeN6LZJ/3cRaOTjSFy6+S6
27
+ zqDmHBp8fVA2TGJtO0BLNkbGVrBJjh0UPmSoGzWlRhEVnYC33TpDAbNA+u39UrQI
28
+ ynwhNN7YbnmSR7+JU2cUjBFv2iPBO+TGuWC+9L2zn3NHjuc6tnmSYipA9y8Hv+As
29
+ Y4evBVezr3SjXz08vPqRO5YRdO3zfeMT8gBjRqZjWJGMZ2lD4XNfrs7eky74CyZw
30
+ xx3n58i0lQkBE1EpKE0lFu/y
37
31
  -----END CERTIFICATE-----
38
-
39
- date: 2013-07-24 00:00:00 Z
40
- dependencies:
41
- - !ruby/object:Gem::Dependency
32
+ date: 2014-05-30 00:00:00.000000000 Z
33
+ dependencies:
34
+ - !ruby/object:Gem::Dependency
42
35
  name: sexp_processor
43
- prerelease: false
44
- requirement: &id001 !ruby/object:Gem::Requirement
45
- none: false
46
- requirements:
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
47
38
  - - ~>
48
- - !ruby/object:Gem::Version
49
- hash: 27
50
- segments:
51
- - 4
52
- - 0
53
- version: "4.0"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
54
41
  type: :runtime
55
- version_requirements: *id001
56
- - !ruby/object:Gem::Dependency
57
- name: ruby_parser
58
42
  prerelease: false
59
- requirement: &id002 !ruby/object:Gem::Requirement
60
- none: false
61
- requirements:
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
62
45
  - - ~>
63
- - !ruby/object:Gem::Version
64
- hash: 7
65
- segments:
66
- - 3
67
- - 0
68
- version: "3.0"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: ruby_parser
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
69
55
  type: :runtime
70
- version_requirements: *id002
71
- - !ruby/object:Gem::Dependency
72
- name: minitest
73
56
  prerelease: false
74
- requirement: &id003 !ruby/object:Gem::Requirement
75
- none: false
76
- requirements:
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
77
59
  - - ~>
78
- - !ruby/object:Gem::Version
79
- hash: 31
80
- segments:
81
- - 5
82
- - 0
83
- version: "5.0"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: minitest
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '5.3'
84
69
  type: :development
85
- version_requirements: *id003
86
- - !ruby/object:Gem::Dependency
87
- name: rdoc
88
70
  prerelease: false
89
- requirement: &id004 !ruby/object:Gem::Requirement
90
- none: false
91
- requirements:
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
92
73
  - - ~>
93
- - !ruby/object:Gem::Version
94
- hash: 27
95
- segments:
96
- - 4
97
- - 0
98
- version: "4.0"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.3'
76
+ - !ruby/object:Gem::Dependency
77
+ name: rdoc
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '4.0'
99
83
  type: :development
100
- version_requirements: *id004
101
- - !ruby/object:Gem::Dependency
102
- name: hoe
103
84
  prerelease: false
104
- requirement: &id005 !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '4.0'
90
+ - !ruby/object:Gem::Dependency
91
+ name: hoe
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
107
94
  - - ~>
108
- - !ruby/object:Gem::Version
109
- hash: 9
110
- segments:
111
- - 3
112
- - 7
113
- version: "3.7"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.12'
114
97
  type: :development
115
- version_requirements: *id005
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '3.12'
116
104
  description: |-
117
105
  Flay analyzes code for structural similarities. Differences in literal
118
106
  values, variable, class, method names, whitespace, programming style,
119
107
  braces vs do/end, etc are all ignored. Making this totally rad.
120
- email:
108
+ email:
121
109
  - ryand-ruby@zenspider.com
122
- executables:
110
+ executables:
123
111
  - flay
124
112
  extensions: []
125
-
126
- extra_rdoc_files:
113
+ extra_rdoc_files:
127
114
  - History.txt
128
115
  - Manifest.txt
129
116
  - README.txt
130
- files:
117
+ files:
118
+ - .gemtest
131
119
  - History.txt
132
120
  - Manifest.txt
133
121
  - README.txt
@@ -138,40 +126,31 @@ files:
138
126
  - lib/flay_task.rb
139
127
  - lib/gauntlet_flay.rb
140
128
  - test/test_flay.rb
141
- - .gemtest
142
129
  homepage: http://ruby.sadi.st/
143
- licenses:
130
+ licenses:
144
131
  - MIT
132
+ metadata: {}
145
133
  post_install_message:
146
- rdoc_options:
134
+ rdoc_options:
147
135
  - --main
148
136
  - README.txt
149
- require_paths:
137
+ require_paths:
150
138
  - lib
151
- required_ruby_version: !ruby/object:Gem::Requirement
152
- none: false
153
- requirements:
154
- - - ">="
155
- - !ruby/object:Gem::Version
156
- hash: 3
157
- segments:
158
- - 0
159
- version: "0"
160
- required_rubygems_version: !ruby/object:Gem::Requirement
161
- none: false
162
- requirements:
163
- - - ">="
164
- - !ruby/object:Gem::Version
165
- hash: 3
166
- segments:
167
- - 0
168
- version: "0"
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
169
149
  requirements: []
170
-
171
- rubyforge_project: seattlerb
172
- rubygems_version: 1.8.25
150
+ rubyforge_project:
151
+ rubygems_version: 2.2.1
173
152
  signing_key:
174
- specification_version: 3
153
+ specification_version: 4
175
154
  summary: Flay analyzes code for structural similarities
176
- test_files:
155
+ test_files:
177
156
  - test/test_flay.rb
metadata.gz.sig CHANGED
Binary file