edouard-metric_fu 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -1
- data/Rakefile +4 -4
- data/spec/base/configuration_spec.rb +1 -1
- data/spec/base/generator_spec.rb +0 -22
- data/spec/generators/churn_spec.rb +7 -7
- data/spec/generators/flay_spec.rb +0 -3
- data/spec/generators/flog_spec.rb +1 -9
- data/spec/generators/reek_spec.rb +0 -1
- data/spec/generators/saikuro_spec.rb +11 -21
- metadata +18 -56
- data/lib/base/base_template.rb +0 -134
- data/lib/base/configuration.rb +0 -207
- data/lib/base/generator.rb +0 -160
- data/lib/base/graph.rb +0 -37
- data/lib/base/md5_tracker.rb +0 -52
- data/lib/base/report.rb +0 -100
- data/lib/generators/churn.rb +0 -91
- data/lib/generators/flay.rb +0 -34
- data/lib/generators/flog.rb +0 -133
- data/lib/generators/rcov.rb +0 -87
- data/lib/generators/reek.rb +0 -37
- data/lib/generators/roodi.rb +0 -31
- data/lib/generators/saikuro.rb +0 -209
- data/lib/generators/stats.rb +0 -43
- data/lib/graphs/flay_grapher.rb +0 -34
- data/lib/graphs/flog_grapher.rb +0 -37
- data/lib/graphs/rcov_grapher.rb +0 -34
- data/lib/graphs/reek_grapher.rb +0 -44
- data/lib/graphs/roodi_grapher.rb +0 -34
- data/lib/metric_fu.rb +0 -24
- data/lib/templates/awesome/awesome_template.rb +0 -30
- data/lib/templates/awesome/churn.html.erb +0 -19
- data/lib/templates/awesome/default.css +0 -66
- data/lib/templates/awesome/flay.html.erb +0 -27
- data/lib/templates/awesome/flog.html.erb +0 -46
- data/lib/templates/awesome/index.html.erb +0 -28
- data/lib/templates/awesome/layout.html.erb +0 -27
- data/lib/templates/awesome/rcov.html.erb +0 -36
- data/lib/templates/awesome/reek.html.erb +0 -34
- data/lib/templates/awesome/roodi.html.erb +0 -21
- data/lib/templates/awesome/saikuro.html.erb +0 -71
- data/lib/templates/awesome/stats.html.erb +0 -41
- data/lib/templates/standard/churn.html.erb +0 -31
- data/lib/templates/standard/default.css +0 -64
- data/lib/templates/standard/flay.html.erb +0 -34
- data/lib/templates/standard/flog.html.erb +0 -53
- data/lib/templates/standard/index.html.erb +0 -38
- data/lib/templates/standard/rcov.html.erb +0 -43
- data/lib/templates/standard/reek.html.erb +0 -42
- data/lib/templates/standard/roodi.html.erb +0 -29
- data/lib/templates/standard/saikuro.html.erb +0 -84
- data/lib/templates/standard/standard_template.rb +0 -26
- data/lib/templates/standard/stats.html.erb +0 -55
- data/tasks/metric_fu.rake +0 -19
- data/tasks/railroad.rake +0 -39
- data/vendor/_fonts/monaco.ttf +0 -0
- data/vendor/saikuro/saikuro.rb +0 -1214
data/lib/generators/reek.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
module MetricFu
|
2
|
-
|
3
|
-
class Reek < Generator
|
4
|
-
REEK_REGEX = /^(\S+) (.*) \((.*)\)$/
|
5
|
-
|
6
|
-
def self.verify_dependencies!
|
7
|
-
`reek --help`
|
8
|
-
raise 'sudo gem install reek # if you want the reek tasks' unless $?.success?
|
9
|
-
end
|
10
|
-
|
11
|
-
def emit
|
12
|
-
files_to_reek = MetricFu.reek[:dirs_to_reek].map{|dir| Dir[File.join(dir, "**/*.rb")] }
|
13
|
-
@output = `reek #{files_to_reek.join(" ")}`
|
14
|
-
end
|
15
|
-
|
16
|
-
def analyze
|
17
|
-
@matches = @output.chomp.split("\n\n").map{|m| m.split("\n") }
|
18
|
-
@matches = @matches.map do |match|
|
19
|
-
file_path = match.shift.split('--').first
|
20
|
-
file_path = file_path.gsub('"', ' ').strip
|
21
|
-
code_smells = match.map do |smell|
|
22
|
-
match_object = smell.match(REEK_REGEX)
|
23
|
-
next unless match_object
|
24
|
-
{:method => match_object[1].strip,
|
25
|
-
:message => match_object[2].strip,
|
26
|
-
:type => match_object[3].strip}
|
27
|
-
end.compact
|
28
|
-
{:file_path => file_path, :code_smells => code_smells}
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_h
|
33
|
-
{:reek => {:matches => @matches}}
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
data/lib/generators/roodi.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
module MetricFu
|
2
|
-
class Roodi < Generator
|
3
|
-
|
4
|
-
def self.verify_dependencies!
|
5
|
-
`roodi --help`
|
6
|
-
raise 'sudo gem install roodi # if you want the roodi tasks' unless $?.success?
|
7
|
-
end
|
8
|
-
|
9
|
-
|
10
|
-
def emit
|
11
|
-
files_to_analyze = MetricFu.roodi[:dirs_to_roodi].map{|dir| Dir[File.join(dir, "**/*.rb")] }
|
12
|
-
@output = `roodi #{files_to_analyze.join(" ")}`
|
13
|
-
end
|
14
|
-
|
15
|
-
def analyze
|
16
|
-
@matches = @output.chomp.split("\n").map{|m| m.split(" - ") }
|
17
|
-
total = @matches.pop
|
18
|
-
@matches.reject! {|array| array.empty? }
|
19
|
-
@matches.map! do |match|
|
20
|
-
file, line = match[0].split(':')
|
21
|
-
problem = match[1]
|
22
|
-
{:file => file, :line => line, :problem => problem}
|
23
|
-
end
|
24
|
-
@roodi_results = {:total => total, :problems => @matches}
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_h
|
28
|
-
{:roodi => @roodi_results}
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/generators/saikuro.rb
DELETED
@@ -1,209 +0,0 @@
|
|
1
|
-
module MetricFu
|
2
|
-
|
3
|
-
class Saikuro < Generator
|
4
|
-
|
5
|
-
def emit
|
6
|
-
relative_path = [File.dirname(__FILE__), '..', '..',
|
7
|
-
'vendor', 'saikuro', 'saikuro.rb']
|
8
|
-
saikuro = File.expand_path(File.join(relative_path))
|
9
|
-
|
10
|
-
format_directories
|
11
|
-
|
12
|
-
options_string = MetricFu.saikuro.inject("") do |options, option|
|
13
|
-
options + "--#{option.join(' ')} "
|
14
|
-
end
|
15
|
-
|
16
|
-
sh %{ruby "#{saikuro}" #{options_string}} do |ok, response|
|
17
|
-
unless ok
|
18
|
-
puts "Saikuro failed with exit status: #{response.exitstatus}"
|
19
|
-
exit 1
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def format_directories
|
25
|
-
dirs = MetricFu.saikuro[:input_directory].join(" | ")
|
26
|
-
dirs = "\"#{dirs}\""
|
27
|
-
MetricFu.saikuro[:input_directory] = dirs
|
28
|
-
end
|
29
|
-
|
30
|
-
def analyze
|
31
|
-
@files = []
|
32
|
-
saikuro_results.each do |path|
|
33
|
-
if Saikuro::SFile.is_valid_text_file?(path)
|
34
|
-
file = Saikuro::SFile.new(path)
|
35
|
-
if file
|
36
|
-
@files << file
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
@files = @files.sort_by do |file|
|
41
|
-
file.elements.
|
42
|
-
max {|a,b| a.complexity.to_i <=> b.complexity.to_i}.
|
43
|
-
complexity.to_i
|
44
|
-
end
|
45
|
-
@files.reverse!
|
46
|
-
klasses = []
|
47
|
-
@files.each {|f| klasses << f.elements}
|
48
|
-
klasses.flatten!
|
49
|
-
@classes = klasses.sort_by {|k| k.complexity.to_i}
|
50
|
-
@classes.reverse!
|
51
|
-
meths = []
|
52
|
-
@files.each {|f|
|
53
|
-
f.elements.each {|el|
|
54
|
-
el.defs.each {|defn|
|
55
|
-
defn.name = "#{el.name}##{defn.name}"
|
56
|
-
meths << defn}
|
57
|
-
}
|
58
|
-
}
|
59
|
-
meths = meths.sort_by {|meth| meth.complexity.to_i}
|
60
|
-
@meths = meths.reverse
|
61
|
-
end
|
62
|
-
|
63
|
-
def to_h
|
64
|
-
files = @files.map do |file|
|
65
|
-
my_file = file.to_h
|
66
|
-
my_file[:filename] = file.filename
|
67
|
-
my_file
|
68
|
-
end
|
69
|
-
{:saikuro => {:files => files,
|
70
|
-
:classes => @classes.map {|c| c.to_h},
|
71
|
-
:methods => @meths.map {|m| m.to_h}
|
72
|
-
}
|
73
|
-
}
|
74
|
-
end
|
75
|
-
|
76
|
-
def saikuro_results
|
77
|
-
Dir.glob("#{metric_directory}/**/*.html")
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
class Saikuro::SFile
|
82
|
-
|
83
|
-
attr_reader :elements
|
84
|
-
|
85
|
-
def initialize(path)
|
86
|
-
@path = path
|
87
|
-
@file_handle = File.open(@path, "r")
|
88
|
-
@elements = []
|
89
|
-
get_elements
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.is_valid_text_file?(path)
|
93
|
-
File.open(path, "r") do |f|
|
94
|
-
if f.eof? || !f.readline.match(/--/)
|
95
|
-
return false
|
96
|
-
else
|
97
|
-
return true
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def filename
|
103
|
-
File.basename(@path, '_cyclo.html')
|
104
|
-
end
|
105
|
-
|
106
|
-
def to_h
|
107
|
-
merge_classes
|
108
|
-
{:classes => @elements}
|
109
|
-
end
|
110
|
-
|
111
|
-
def get_elements
|
112
|
-
begin
|
113
|
-
while (line = @file_handle.readline) do
|
114
|
-
return [] if line.nil? || line !~ /\S/
|
115
|
-
element ||= nil
|
116
|
-
if line.match /START/
|
117
|
-
unless element.nil?
|
118
|
-
@elements << element
|
119
|
-
element = nil
|
120
|
-
end
|
121
|
-
line = @file_handle.readline
|
122
|
-
element = Saikuro::ParsingElement.new(line)
|
123
|
-
elsif line.match /END/
|
124
|
-
@elements << element unless element.nil?
|
125
|
-
element = nil
|
126
|
-
else
|
127
|
-
element << line
|
128
|
-
end
|
129
|
-
end
|
130
|
-
rescue EOFError
|
131
|
-
nil
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
|
136
|
-
def merge_classes
|
137
|
-
new_elements = []
|
138
|
-
get_class_names.each do |target_class|
|
139
|
-
elements = @elements.find_all {|el| el.name == target_class }
|
140
|
-
complexity = 0
|
141
|
-
lines = 0
|
142
|
-
defns = []
|
143
|
-
elements.each do |el|
|
144
|
-
complexity += el.complexity.to_i
|
145
|
-
lines += el.lines.to_i
|
146
|
-
defns << el.defs
|
147
|
-
end
|
148
|
-
|
149
|
-
new_element = {:class_name => target_class,
|
150
|
-
:complexity => complexity,
|
151
|
-
:lines => lines,
|
152
|
-
:methods => defns.flatten.map {|d| d.to_h}}
|
153
|
-
new_element[:methods] = new_element[:methods].
|
154
|
-
sort_by {|x| x[:complexity] }.
|
155
|
-
reverse
|
156
|
-
|
157
|
-
new_elements << new_element
|
158
|
-
end
|
159
|
-
@elements = new_elements if new_elements
|
160
|
-
end
|
161
|
-
|
162
|
-
def get_class_names
|
163
|
-
class_names = []
|
164
|
-
@elements.each do |element|
|
165
|
-
unless class_names.include?(element.name)
|
166
|
-
class_names << element.name
|
167
|
-
end
|
168
|
-
end
|
169
|
-
class_names
|
170
|
-
end
|
171
|
-
|
172
|
-
end
|
173
|
-
|
174
|
-
class Saikuro::ParsingElement
|
175
|
-
TYPE_REGEX=/Type:(.*) Name/
|
176
|
-
NAME_REGEX=/Name:(.*) Complexity/
|
177
|
-
COMPLEXITY_REGEX=/Complexity:(.*) Lines/
|
178
|
-
LINES_REGEX=/Lines:(.*)/
|
179
|
-
|
180
|
-
attr_reader :complexity, :lines, :defs, :element_type
|
181
|
-
attr_accessor :name
|
182
|
-
|
183
|
-
def initialize(line)
|
184
|
-
@line = line
|
185
|
-
@element_type = line.match(TYPE_REGEX)[1].strip
|
186
|
-
@name = line.match(NAME_REGEX)[1].strip
|
187
|
-
@complexity = line.match(COMPLEXITY_REGEX)[1].strip
|
188
|
-
@lines = line.match(LINES_REGEX)[1].strip
|
189
|
-
@defs = []
|
190
|
-
end
|
191
|
-
|
192
|
-
def <<(line)
|
193
|
-
@defs << Saikuro::ParsingElement.new(line)
|
194
|
-
end
|
195
|
-
|
196
|
-
def to_h
|
197
|
-
base = {:name => @name, :complexity => @complexity.to_i, :lines => @lines.to_i}
|
198
|
-
unless @defs.empty?
|
199
|
-
defs = @defs.map do |my_def|
|
200
|
-
my_def = my_def.to_h
|
201
|
-
my_def.delete(:defs)
|
202
|
-
my_def
|
203
|
-
end
|
204
|
-
base[:defs] = defs
|
205
|
-
end
|
206
|
-
return base
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
data/lib/generators/stats.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
module MetricFu
|
2
|
-
|
3
|
-
class Stats < Generator
|
4
|
-
|
5
|
-
def emit
|
6
|
-
`rake stats > #{metric_directory + '/stats.txt'}`
|
7
|
-
end
|
8
|
-
|
9
|
-
def analyze
|
10
|
-
output = File.open(metric_directory + '/stats.txt').read
|
11
|
-
output = output.split("\n")
|
12
|
-
output = output.find_all {|line| line[0].chr != "+" }
|
13
|
-
output = output.find_all {|line| line[0].chr != "(" }
|
14
|
-
output.shift
|
15
|
-
totals = output.pop
|
16
|
-
totals = totals.split(" ").find_all {|el| ! el.empty? }
|
17
|
-
@stats = {}
|
18
|
-
@stats[:codeLOC] = totals[0].match(/\d.*/)[0].to_i
|
19
|
-
@stats[:testLOC] = totals[1].match(/\d.*/)[0].to_i
|
20
|
-
@stats[:code_to_test_ratio] = totals[2].match(/1\:(\d.*)/)[1].to_f
|
21
|
-
|
22
|
-
@stats[:lines] = output.map do |line|
|
23
|
-
elements = line.split("|")
|
24
|
-
elements.map! {|el| el.strip }
|
25
|
-
elements = elements.find_all {|el| ! el.empty? }
|
26
|
-
info_line = {}
|
27
|
-
info_line[:name] = elements.shift
|
28
|
-
elements.map! {|el| el.to_i }
|
29
|
-
[:lines, :loc, :classes, :methods,
|
30
|
-
:methods_per_class, :loc_per_method].each do |sym|
|
31
|
-
info_line[sym] = elements.shift
|
32
|
-
end
|
33
|
-
info_line
|
34
|
-
end
|
35
|
-
@stats
|
36
|
-
end
|
37
|
-
|
38
|
-
def to_h
|
39
|
-
{:stats => @stats}
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
data/lib/graphs/flay_grapher.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'gruff'
|
2
|
-
module MetricFu
|
3
|
-
|
4
|
-
class FlayGrapher
|
5
|
-
|
6
|
-
attr_accessor :flay_score, :labels
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
self.flay_score = []
|
10
|
-
self.labels = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_metrics(metrics, date)
|
14
|
-
self.flay_score.push(metrics[:flay][:total_score].to_i)
|
15
|
-
self.labels.update( { self.labels.size => date })
|
16
|
-
end
|
17
|
-
|
18
|
-
def graph!
|
19
|
-
g = Gruff::Line.new(MetricFu.graph_size)
|
20
|
-
g.title = "Flay: duplication"
|
21
|
-
g.theme = MetricFu.graph_theme
|
22
|
-
g.font = MetricFu.graph_font
|
23
|
-
g.data('flay', self.flay_score)
|
24
|
-
g.labels = self.labels
|
25
|
-
g.title_font_size = MetricFu.graph_title_font_size
|
26
|
-
g.legend_box_size = MetricFu.graph_legend_box_size
|
27
|
-
g.legend_font_size = MetricFu.graph_legend_font_size
|
28
|
-
g.marker_font_size = MetricFu.graph_marker_font_size
|
29
|
-
g.write(File.join(MetricFu.output_directory, 'flay.png'))
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
data/lib/graphs/flog_grapher.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'gruff'
|
2
|
-
module MetricFu
|
3
|
-
|
4
|
-
class FlogGrapher
|
5
|
-
|
6
|
-
attr_accessor :flog_total, :flog_average, :labels
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
self.flog_total = []
|
10
|
-
self.flog_average = []
|
11
|
-
self.labels = {}
|
12
|
-
end
|
13
|
-
|
14
|
-
def get_metrics(metrics, date)
|
15
|
-
self.flog_total.push(metrics[:flog][:total])
|
16
|
-
self.flog_average.push(metrics[:flog][:average])
|
17
|
-
self.labels.update( { self.labels.size => date })
|
18
|
-
end
|
19
|
-
|
20
|
-
def graph!
|
21
|
-
g = Gruff::Line.new(MetricFu.graph_size)
|
22
|
-
g.title = "Flog: code complexity"
|
23
|
-
g.theme = MetricFu.graph_theme
|
24
|
-
g.font = MetricFu.graph_font
|
25
|
-
g.data('flog total', self.flog_total)
|
26
|
-
g.data('flog average', self.flog_average)
|
27
|
-
g.labels = self.labels
|
28
|
-
g.title_font_size = MetricFu.graph_title_font_size
|
29
|
-
g.legend_box_size = MetricFu.graph_legend_box_size
|
30
|
-
g.legend_font_size = MetricFu.graph_legend_font_size
|
31
|
-
g.marker_font_size = MetricFu.graph_marker_font_size
|
32
|
-
g.write(File.join(MetricFu.output_directory, 'flog.png'))
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
data/lib/graphs/rcov_grapher.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'gruff'
|
2
|
-
module MetricFu
|
3
|
-
|
4
|
-
class RcovGrapher
|
5
|
-
|
6
|
-
attr_accessor :rcov_percent, :labels
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
self.rcov_percent = []
|
10
|
-
self.labels = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_metrics(metrics, date)
|
14
|
-
self.rcov_percent.push(metrics[:rcov][:global_percent_run])
|
15
|
-
self.labels.update( { self.labels.size => date })
|
16
|
-
end
|
17
|
-
|
18
|
-
def graph!
|
19
|
-
g = Gruff::Line.new(MetricFu.graph_size)
|
20
|
-
g.title = "Rcov: code coverage"
|
21
|
-
g.theme = MetricFu.graph_theme
|
22
|
-
g.font = MetricFu.graph_font
|
23
|
-
g.data('rcov', self.rcov_percent)
|
24
|
-
g.labels = self.labels
|
25
|
-
g.title_font_size = MetricFu.graph_title_font_size
|
26
|
-
g.legend_box_size = MetricFu.graph_legend_box_size
|
27
|
-
g.legend_font_size = MetricFu.graph_legend_font_size
|
28
|
-
g.marker_font_size = MetricFu.graph_marker_font_size
|
29
|
-
g.write(File.join(MetricFu.output_directory, 'rcov.png'))
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
data/lib/graphs/reek_grapher.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'gruff'
|
2
|
-
module MetricFu
|
3
|
-
|
4
|
-
class ReekGrapher
|
5
|
-
|
6
|
-
attr_accessor :reek_count, :labels
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
self.reek_count = {}
|
10
|
-
self.labels= {}
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_metrics(metrics, date)
|
14
|
-
counter = self.labels.size
|
15
|
-
self.labels.update( { counter => date })
|
16
|
-
|
17
|
-
metrics[:reek][:matches].each do |reek_chunk|
|
18
|
-
reek_chunk[:code_smells].each do |code_smell|
|
19
|
-
# speaking of code smell...
|
20
|
-
self.reek_count[code_smell[:type]] = [] if self.reek_count[code_smell[:type]].nil?
|
21
|
-
self.reek_count[code_smell[:type]][counter].nil? ? self.reek_count[code_smell[:type]][counter] = 1 : self.reek_count[code_smell[:type]][counter] += 1
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def graph!
|
27
|
-
g = Gruff::Line.new(MetricFu.graph_size)
|
28
|
-
g.title = "Reek: code smells"
|
29
|
-
g.theme = MetricFu.graph_theme
|
30
|
-
g.font = MetricFu.graph_font
|
31
|
-
self.reek_count.each_pair do |type, count|
|
32
|
-
g.data(type, count)
|
33
|
-
end
|
34
|
-
g.labels = self.labels
|
35
|
-
g.title_font_size = MetricFu.graph_title_font_size
|
36
|
-
g.legend_box_size = MetricFu.graph_legend_box_size
|
37
|
-
g.legend_font_size = MetricFu.graph_legend_font_size
|
38
|
-
g.marker_font_size = MetricFu.graph_marker_font_size
|
39
|
-
g.write(File.join(MetricFu.output_directory, 'reek.png'))
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|