Skip to content

Commit

Permalink
Cane metrics added
Browse files Browse the repository at this point in the history
  • Loading branch information
sathish316 committed Mar 4, 2013
1 parent f76bf2f commit 8a23da5
Show file tree
Hide file tree
Showing 16 changed files with 478 additions and 5 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ spec/reports
test/tmp
test/version_tmp
tmp

*.swp
tags
9 changes: 9 additions & 0 deletions bin/mf-cane
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env ruby_noexec_wrapper
require 'rubygems'

require 'metric_fu_requires'

gem 'parallel', MetricFu::MetricVersion.parallel
version = MetricFu::MetricVersion.cane
gem 'cane', version
load Gem.bin_path('cane', 'cane', version)
72 changes: 72 additions & 0 deletions lib/metric_fu/metrics/cane/cane.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require 'cane'

module MetricFu
class Cane < Generator
attr_reader :violations, :total_violations

def emit
command = %Q{mf-cane#{abc_max_param}#{style_measure_param}#{no_doc_param}}
mf_debug = "** #{command}"
@output = `#{command}`
end

def analyze
@violations = violations_by_category
extract_total_violations
end

def to_h
{:cane => {:total_violations => @total_violations, :violations => @violations}}
end
private

def abc_max_param
MetricFu.cane[:abc_max] ? " --abc-max #{MetricFu.cane[:abc_max]}" : ""
end

def style_measure_param
MetricFu.cane[:line_length] ? " --style-measure #{MetricFu.cane[:line_length]}" : ""
end

def no_doc_param
MetricFu.cane[:no_doc] == 'y' ? " --no-doc" : ""
end

def violations_by_category
violations_output = @output.scan(/(.*?)\n\n(.*?)\n\n/m)
violations_output.each_with_object({}) do |(category_desc, violation_list), violations|
category = category_from(category_desc)
violations[category] = violations_for(category, violation_list)
end
end

def category_from(description)
category_descriptions = {
:abc_complexity => /ABC complexity/,
:line_style => /style requirements/,
:comment => /comment/
}
category_descriptions.find {|k,v| description =~ v}[0]
end

def violations_for(category, violation_list)
violation_type_for(category).parse(violation_list)
end

def violation_type_for(category)
case category
when :abc_complexity
CaneViolations::AbcComplexity
when :line_style
CaneViolations::LineStyle
when :comment
CaneViolations::Comment
end
end

def extract_total_violations
total = @output.match(/Total Violations: (\d+)/)[1]
@total_violations = total.to_i if total
end
end
end
19 changes: 19 additions & 0 deletions lib/metric_fu/metrics/cane/cane_grapher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module MetricFu
class CaneGrapher < Grapher
attr_accessor :cane_violations, :labels

def initialize
super
@cane_violations = []
@labels = {}
end

def get_metrics(metrics, date)
if metrics && metrics[:cane]
@cane_violations.push(metrics[:cane][:total_violations].to_i)
@labels.update( { @labels.size => date })
end
end
end
end

12 changes: 12 additions & 0 deletions lib/metric_fu/metrics/cane/init.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
MetricFu::Configuration.run do |config|
config.add_metric(:cane)
config.add_graph(:cane)
config.configure_metric(:cane, {
:dirs_to_cane => MetricFu.code_dirs,
:abc_max => 15,
:line_length => 80,
:no_doc => 'n',
:filetypes => ['rb']
})
end

78 changes: 78 additions & 0 deletions lib/metric_fu/metrics/cane/template_awesome/cane.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<html>
<head>
<title>Cane Results</title>
<style>
<%= inline_css("css/default.css") %>
</style>
</head>

<body>
<h1>Cane Results</h1>
<a href="index.html">back to menu</a>
<h2>Total Violations: <%= @cane[:total_violations] %></h2>
<p><a href='https://github.com/square/cane'>Cane</a> reports code quality threshold violations.</p>

<% graph_name = 'cane' %>
<% if MetricFu.configuration.graph_engine == :gchart %>
<img src="<%= graph_name %>.png?<%= Time.now.to_i %>" />
<% else %>
<canvas id="graph"></canvas>
<script language="javascript" src="<%= graph_name %>.js?<%= Time.now.to_i %>" type="text/javascript"></script>
<% end %>

<% if @cane[:violations][:abc_complexity] && @cane[:violations][:abc_complexity].size > 0 %>
<h3>Methods exceeding allowed Abc complexity (<%= @cane[:violations][:abc_complexity].size %>)</h3>
<table>
<tr>
<th>File</th>
<th>Method</th>
<th>Complexity</th>
</tr>
<% count = 0 %>
<% @cane[:violations][:abc_complexity].each do |violation| %>
<tr class='<%= cycle("light", "dark", count) %>'>
<td><%=violation[:file]%></td>
<td><%=violation[:method]%></td>
<td><%=violation[:complexity]%></td>
</tr>
<% count += 1 %>
<% end %>
</table>
<% end %>
<% if @cane[:violations][:line_style] && @cane[:violations][:line_style].size > 0 %>
<h3>Lines violating style requirements (<%= @cane[:violations][:line_style].size %>)</h3>
<table>
<tr>
<th>File</th>
<th>Description</th>
</tr>
<% count = 0 %>
<% @cane[:violations][:line_style].each do |violation| %>
<tr class='<%= cycle("light", "dark", count) %>'>
<td><%=violation[:line]%></td>
<td><%=violation[:description]%></td>
</tr>
<% count += 1 %>
<% end %>
</table>
<% end %>
<% if @cane[:violations][:comment] && @cane[:violations][:comment].size > 0 %>
<h3>Class definitions requiring comments (<%= @cane[:violations][:comment].size %>)</h3>
<table>
<tr>
<th>File</th>
<th>Class</th>
</tr>
<% count = 0 %>
<% @cane[:violations][:comment].each do |violation| %>
<tr class='<%= cycle("light", "dark", count) %>'>
<td><%=violation[:line]%></td>
<td><%=violation[:class_name]%></td>
</tr>
<% count += 1 %>
<% end %>
</table>
<% end %>
<p>Generated on <%= Time.now.localtime %></p>
</body>
</html>
69 changes: 69 additions & 0 deletions lib/metric_fu/metrics/cane/template_standard/cane.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<html>
<head>
<title>Cane Results</title>
<style>
<%= inline_css("default.css") %>
</style>
</head>

<body>
<h1>Cane Results</h1>
<a href="index.html">back to menu</a>
<h2>Total Violations: <%= @cane[:total_violations] %></h2>
<p><a href='https://github.com/square/cane'>Cane</a> reports code quality threshold violations.</p>
<% if @cane[:violations][:abc_complexity] && @cane[:violations][:abc_complexity].size > 0 %>
<h3>Methods exceeding allowed Abc complexity (<%= @cane[:violations][:abc_complexity].size %>)</h3>
<table>
<tr>
<th>File</th>
<th>Method</th>
<th>Complexity</th>
</tr>
<% count = 0 %>
<% @cane[:violations][:abc_complexity].each do |violation| %>
<tr class='<%= cycle("light", "dark", count) %>'>
<td><%=violation[:file]%></td>
<td><%=violation[:method]%></td>
<td><%=violation[:complexity]%></td>
</tr>
<% count += 1 %>
<% end %>
</table>
<% end %>
<% if @cane[:violations][:line_style] && @cane[:violations][:line_style].size > 0 %>
<h3>Lines violating style requirements (<%= @cane[:violations][:line_style].size %>)</h3>
<table>
<tr>
<th>File</th>
<th>Description</th>
</tr>
<% count = 0 %>
<% @cane[:violations][:line_style].each do |violation| %>
<tr class='<%= cycle("light", "dark", count) %>'>
<td><%=violation[:line]%></td>
<td><%=violation[:description]%></td>
</tr>
<% count += 1 %>
<% end %>
</table>
<% end %>
<% if @cane[:violations][:comment] && @cane[:violations][:comment].size > 0 %>
<h3>Class definitions requiring comments (<%= @cane[:violations][:comment].size %>)</h3>
<table>
<tr>
<th>File</th>
<th>Description</th>
</tr>
<% count = 0 %>
<% @cane[:violations][:comment].each do |violation| %>
<tr class='<%= cycle("light", "dark", count) %>'>
<td><%=violation[:line]%></td>
<td><%=violation[:class_name]%></td>
</tr>
<% count += 1 %>
<% end %>
</table>
<% end %>
<p>Generated on <%= Time.now.localtime %></p>
</body>
</html>
30 changes: 30 additions & 0 deletions lib/metric_fu/metrics/cane/violations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module MetricFu
module CaneViolations
class AbcComplexity
def self.parse(violation_list)
violation_list.split(/\n/).map do |violation|
file, method, complexity = violation.split
{:file => file, :method => method, :complexity => complexity}
end
end
end

class LineStyle
def self.parse(violation_list)
violation_list.split(/\n/).map do |violation|
line, description = violation.split(/\s{2,}/).reject{|x|x.strip==''}
{:line => line, :description => description}
end
end
end

class Comment
def self.parse(violation_list)
violation_list.split(/\n/).map do |violation|
line, class_name = violation.split
{:line => line, :class_name => class_name}
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/metric_fu/reporting/graphs/engines/bluff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,18 @@ def graph!
File.open(File.join(MetricFu.output_directory, 'rails_best_practices.js'), 'w') {|f| f << content }
end
end

class CaneBluffGrapher < CaneGrapher
def graph!
content = <<-EOS
#{BLUFF_DEFAULT_OPTIONS}
g.title = 'Cane: code quality threshold violations';
g.data('cane', [#{@cane_violations.join(',')}]);
g.labels = #{@labels.to_json};
g.draw();
EOS
File.open(File.join(MetricFu.output_directory, 'cane.js'), 'w') {|f| f << content }
end
end

end
3 changes: 3 additions & 0 deletions lib/metric_fu/reporting/templates/awesome/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<% if @saikuro %>
<li class='even failure'><a href="saikuro.html">Saikuro</a></li>
<% end %>
<% if @cane %>
<li class='even failure'><a href="cane.html">Cane</a></li>
<% end %>
<% if @stats %>
<li class='even failure'><a href="stats.html">Stats</a></li>
<% end %>
Expand Down
3 changes: 3 additions & 0 deletions lib/metric_fu/reporting/templates/standard/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<% if @saikuro %>
<p><a href="saikuro.html">Saikuro report</a></p>
<% end %>
<% if @cane %>
<p><a href="cane.html">Cane report</a></p>
<% end %>
<% if @stats %>
<p><a href="stats.html">Stats report</a></p>
<% end %>
Expand Down
6 changes: 6 additions & 0 deletions lib/metric_fu_requires.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,18 @@ def ruby_parser
def sexp_processor
'~> 4.0'
end
def parallel
'0.6.2'
end

def rcov
'~> 0.8'
end
def saikuro
'>= 1.1.1.0'
end
def cane
'2.5.2'
end
end
end
4 changes: 3 additions & 1 deletion metric_fu.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ Gem::Specification.new do |s|
"flog" => ["= #{MetricFu::MetricVersion.flog}"],
"reek" => ["= #{MetricFu::MetricVersion.reek}"],
"churn" => ["= #{MetricFu::MetricVersion.churn}"],
# specifying dependencies for flay, reek, churn, and flog
"cane" => ["= #{MetricFu::MetricVersion.cane}"],
# specifying dependencies for flay, reek, churn, flog, and cane
"ruby_parser" => ["~> 3.0", ">= #{MetricFu::MetricVersion.ruby_parser}"],
"sexp_processor" => ["#{MetricFu::MetricVersion.sexp_processor}"],
"ruby2ruby" => ["= #{MetricFu::MetricVersion.ruby2ruby}"],
"parallel" => ["= #{MetricFu::MetricVersion.parallel}"],
"activesupport" => [">= 2.0.0"], # ok
"coderay" => [],
"fattr" => ["= 2.2.1"],
Expand Down
11 changes: 11 additions & 0 deletions spec/cli/helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
defaults[:saikuro].should be_true
end

it "enables Cane" do
defaults[:cane].should be_true
end

it "enables RCov" do
defaults[:rcov].should be_true
end
Expand Down Expand Up @@ -142,6 +146,13 @@
helper.process_options(["--roodi"])[:roodi].should be_true
end

it "turns cane off" do
helper.process_options(["--no-cane"])[:cane].should be_false
end

it "turns cane on" do
helper.process_options(["--cane"])[:cane].should be_true
end
end

end
Loading

0 comments on commit 8a23da5

Please sign in to comment.