lib/flay.rb in flay-2.4.0 vs lib/flay.rb in flay-2.5.0

- old
+ new

@@ -13,12 +13,20 @@ alias :binread :read unless RUBY19 end end class Flay - VERSION = "2.4.0" # :nodoc: + VERSION = "2.5.0" # :nodoc: + class Item < Struct.new(:structural_hash, :name, :bonus, :mass, :locations) + alias identical? bonus + end + + class Location < Struct.new(:file, :line, :fuzzy) + alias fuzzy? fuzzy + end + ## # Returns the default options. def self.default_options { @@ -28,10 +36,11 @@ :verbose => false, :number => true, :timeout => 10, :liberal => false, :fuzzy => false, + :only => nil, } end ## # Process options in +args+, defaulting to +ARGV+. @@ -72,10 +81,14 @@ opts.on('-v', '--verbose', "Verbose. Show progress processing files.") do options[:verbose] = true end + opts.on('-o', '--only NODE', String, "Only show matches on NODE type.") do |s| + options[:only] = s.to_sym + end + opts.on('-d', '--diff', "Diff Mode. Display N-Way diff for ruby.") do options[:diff] = true end opts.on('-s', '--summary', "Summarize. Show flay score per file only.") do @@ -202,18 +215,43 @@ end ## # Prune, find identical nodes, and update masses. - def analyze + def analyze filter = nil self.prune self.hashes.each do |hash,nodes| identical[hash] = nodes[1..-1].all? { |n| n == nodes.first } end update_masses + + sorted = masses.sort_by { |h,m| + [-m, + hashes[h].first.file, + hashes[h].first.line, + hashes[h].first.first.to_s] + } + + sorted.map { |hash, mass| + nodes = hashes[hash] + + next unless nodes.first.first == filter if filter + + same = identical[hash] + node = nodes.first + n = nodes.size + bonus = "*#{n}" if same + + locs = nodes.sort_by { |x| [x.file, x.line] }.each_with_index.map { |x, i| + extra = :fuzzy if x.modified? + Location[x.file, x.line, extra] + } + + Item[hash, node.first, bonus, mass, locs] + }.compact end ## # Reset total and recalculate the masses for all nodes in +hashes+. @@ -425,73 +463,52 @@ end ## # Output the report. Duh. - def report prune = nil - analyze + def report io = $stdout + only = option[:only] - puts "Total score (lower is better) = #{self.total}" + data = analyze only + io.puts "Total score (lower is better) = #{self.total}" + if option[:summary] then - puts + io.puts self.summary.sort_by { |_,v| -v }.each do |file, score| - puts "%8.2f: %s" % [score, file] + io.puts "%8.2f: %s" % [score, file] end return end - count = 0 - sorted = masses.sort_by { |h,m| - [-m, - hashes[h].first.file, - hashes[h].first.line, - hashes[h].first.first.to_s] - } - sorted.each do |hash, mass| - nodes = hashes[hash] - next unless nodes.first.first == prune if prune - puts + data.each_with_index do |item, count| + prefix = "%d) " % (count + 1) if option[:number] - same = identical[hash] - node = nodes.first - n = nodes.size - match, bonus = if same then - ["IDENTICAL", "*#{n}"] - else - ["Similar", ""] - end + match = item.identical? ? "IDENTICAL" : "Similar" - if option[:number] then - count += 1 + io.puts + io.puts "%s%s code found in %p (mass%s = %d)" % + [prefix, match, item.name, item.bonus, item.mass] - puts "%d) %s code found in %p (mass%s = %d)" % - [count, match, node.first, bonus, mass] - else - puts "%s code found in %p (mass%s = %d)" % - [match, node.first, bonus, mass] + item.locations.each_with_index do |loc, i| + loc_prefix = "%s: " % (?A.ord + i).chr if option[:diff] + extra = " (FUZZY)" if loc.fuzzy? + io.puts " %s%s:%d%s" % [loc_prefix, loc.file, loc.line, extra] end - nodes.sort_by { |x| [x.file, x.line] }.each_with_index do |x, i| - if option[:diff] then - c = (?A.ord + i).chr - extra = " (FUZZY)" if x.modified? - puts " #{c}: #{x.file}:#{x.line}#{extra}" - else - extra = " (FUZZY)" if x.modified? - puts " #{x.file}:#{x.line}#{extra}" - end - end - if option[:diff] then - puts + io.puts + + nodes = hashes[item.structural_hash] + sources = nodes.map do |s| msg = "sexp_to_#{File.extname(s.file).sub(/./, '')}" self.respond_to?(msg) ? self.send(msg, s) : sexp_to_rb(s) end - puts n_way_diff(*sources) + + io.puts n_way_diff(*sources) end end end def sexp_to_rb sexp