metric_fu 2.1.3.4 → 2.1.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data/{HISTORY → HISTORY.md} +18 -2
- data/README.md +11 -7
- data/TODO +1 -0
- data/lib/data_structures/careful_array.rb +8 -6
- data/lib/data_structures/code_issue.rb +82 -78
- data/lib/data_structures/grouping.rb +2 -2
- data/lib/data_structures/table.rb +77 -75
- data/lib/errors/analysis_error.rb +4 -1
- data/lib/metrics/churn/{churn_analyzer.rb → churn_hotspot.rb} +4 -4
- data/lib/metrics/flay/{flay_analyzer.rb → flay_hotspot.rb} +5 -5
- data/lib/metrics/flog/{flog_analyzer.rb → flog_hotspot.rb} +4 -4
- data/lib/metrics/hotspot_analyzer.rb +328 -0
- data/lib/metrics/hotspots/hotspots.rb +1 -1
- data/lib/metrics/rcov/{rcov_analyzer.rb → rcov_hotspot.rb} +4 -4
- data/lib/metrics/reek/{reek_analyzer.rb → reek_hotspot.rb} +7 -7
- data/lib/metrics/roodi/{roodi_analyzer.rb → roodi_hotspot.rb} +5 -5
- data/lib/metrics/saikuro/{saikuro_analyzer.rb → saikuro_hotspot.rb} +4 -4
- data/lib/metrics/stats/{stats_analyzer.rb → stats_hotspot.rb} +1 -1
- data/lib/scoring_strategies.rb +24 -22
- data/lib/version.rb +1 -1
- data/metric_fu.gemspec +1 -1
- data/spec/base/{metric_analyzer_spec.rb → hotspot_analyzer_spec.rb} +92 -92
- data/spec/generators/hotspots_spec.rb +2 -2
- metadata +356 -330
- data/lib/metrics/metric_analyzer.rb +0 -328
data/{HISTORY → HISTORY.md}
RENAMED
@@ -1,3 +1,19 @@
|
|
1
|
+
=== MetricFu 2.1.3.5 / 2013-01-01
|
2
|
+
|
3
|
+
* Issue #35, Namespace MetricFu::Table. -Benjamin Fleischer
|
4
|
+
* Additionally namespace
|
5
|
+
* MetricFu::CodeIssue
|
6
|
+
* MetricFu::MetricAnalyzer
|
7
|
+
* MetricFu::AnalysisError
|
8
|
+
* MetricFu::HotspotScoringStrategies
|
9
|
+
* Rename MetricAnalyzer to HotspotAnalyzer, and rename all <metric>Analzyer classes to <metric>Hotspot to signify that they are part of the Hotspot code -Benjamin Fleischer
|
10
|
+
|
11
|
+
=== MetricFu 2.1.3.4 / 2012-12-28
|
12
|
+
|
13
|
+
* Restructuring of the project layout
|
14
|
+
* Project is now at https://github.com/metricfu/metric_fu and gem is again metric_fu
|
15
|
+
* Can run tasks as `metric_fu` command
|
16
|
+
|
1
17
|
=== MetricFu 2.1.3.2 / 2012-11-14
|
2
18
|
|
3
19
|
* Don't raise an exception in the LineNumbers rescue block. Issue https://github.com/bf4/metric_fu/issues/6 by joonty -Benjamin Fleischer
|
@@ -17,7 +33,7 @@
|
|
17
33
|
* Getting it working on Rails 3, partly by going through the pull requests and setting gem dependencies to older, working versions - Benjamin Fleischer
|
18
34
|
* It mostly works on Ruby 1.9, though there is an unresolved sexp_parser issue - Benjamin Fleischer
|
19
35
|
* Added link_prefix to configuration to allow URIs specified in config instead of file or txmt - dan sinclair
|
20
|
-
|
36
|
+
|
21
37
|
=== MetricFu 2.1.1 / 2011-03-2
|
22
38
|
|
23
39
|
* Making syntax highlighting optional (config.syntax_highlighting = false) so Ruby 1.9.2 users don't get "invalid byte sequence in UTF-8" errors.
|
@@ -31,7 +47,7 @@
|
|
31
47
|
* Stefan Huber fixed some problems with churn pretending not to support Svn.
|
32
48
|
* Kakutani Shintaro added the ability to opt out of opening files with TextMate (config.darwin_txmt_protocol_no_thanks = true).
|
33
49
|
* Joel Nimety and Andrew Selder fixed a problem where Saikuro was parsing a dir twice.
|
34
|
-
* Dan Sinclair added some awesome 'annotate' functionality to the Hotspots page. Click on it so see the file with problems in-line.
|
50
|
+
* Dan Sinclair added some awesome 'annotate' functionality to the Hotspots page. Click on it so see the file with problems in-line.
|
35
51
|
* Dan Sinclair added a verbose mode (config.verbose = true).
|
36
52
|
|
37
53
|
=== MetricFu 2.0.1 / 2010-11-13
|
data/README.md
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
This
|
1
|
+
This is the official repository for metric_fu.
|
2
2
|
|
3
|
-
|
3
|
+
It is currently testing on MRI 1.8.7 and 1.9.3
|
4
4
|
|
5
|
-
|
5
|
+
The original repository by Jake Scruggs at [https://github.com/jscruggs/metric_fu](https://github.com/jscruggs/metric_fu) [has been deprecated.](http://jakescruggs.blogspot.com/2012/08/why-i-abandoned-metricfu.html).
|
6
|
+
|
7
|
+
The gem is published on rubygems.org as metric_fu
|
8
|
+
|
9
|
+
There is also a related metricfu-metrical gem published
|
6
10
|
|
7
11
|
The japgolly-Saikuro fork is a part of an attempt to get metric_fu working in a modern
|
8
12
|
|
@@ -12,13 +16,13 @@ Ruby environment, specifically compatibility with Ruby 1.9 and Bundler.
|
|
12
16
|
|
13
17
|
__CI Build Status__
|
14
18
|
|
15
|
-
[![Build Status](https://secure.travis-ci.org/
|
19
|
+
[![Build Status](https://secure.travis-ci.org/metricfu/metric_fu.png)](http://travis-ci.org/metricfu/metric_fu)
|
16
20
|
|
17
21
|
This project runs [travis-ci.org](http://travis-ci.org)
|
18
22
|
|
19
23
|
__Code Quality__
|
20
24
|
|
21
|
-
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/
|
25
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/metricfu/metric_fu)
|
22
26
|
|
23
27
|
This project runs [https://codeclimate.com/](https://codeclimate.com/)
|
24
28
|
|
@@ -48,8 +52,8 @@ The more of the above steps you do the easier it will be for me to merge in whic
|
|
48
52
|
|
49
53
|
Resources:
|
50
54
|
|
51
|
-
Github: http://github.com/
|
52
|
-
Issue Tracker: http://github.com/
|
55
|
+
Github: http://github.com/metricfu/metric_fu
|
56
|
+
Issue Tracker: http://github.com/metricfu/metric_fu/issues
|
53
57
|
My Blog: http://benjaminfleischer.com
|
54
58
|
|
55
59
|
Original Resources:
|
data/TODO
CHANGED
@@ -5,4 +5,5 @@
|
|
5
5
|
* Color code flog results with scale from: http://jakescruggs.blogspot.com/2008/08/whats-good-flog-score.html
|
6
6
|
* Make running metric_fu on metric_fu less embarrassing
|
7
7
|
* Load all gems at config time so you fail fast if one is missing
|
8
|
+
* Look into removing rcov and churn, and adding laser, brakeman, and/or cane
|
8
9
|
|
@@ -1,9 +1,11 @@
|
|
1
|
-
module
|
1
|
+
module MetricFu
|
2
|
+
module CarefulArray
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
def carefully_remove(elements)
|
5
|
+
missing_elements = elements - self
|
6
|
+
raise "Cannot delete missing elements: #{missing_elements.inspect}" unless missing_elements.empty?
|
7
|
+
(self - elements).extend(MetricFu::CarefulArray)
|
8
|
+
end
|
8
9
|
|
10
|
+
end
|
9
11
|
end
|
@@ -1,98 +1,102 @@
|
|
1
1
|
require 'delegate'
|
2
2
|
|
3
|
-
[ '
|
4
|
-
'flog/
|
5
|
-
'saikuro/
|
6
|
-
'churn/
|
7
|
-
'reek/
|
8
|
-
'flay/
|
3
|
+
[ 'hotspot_analyzer',
|
4
|
+
'flog/flog_hotspot',
|
5
|
+
'saikuro/saikuro_hotspot',
|
6
|
+
'churn/churn_hotspot',
|
7
|
+
'reek/reek_hotspot',
|
8
|
+
'flay/flay_hotspot'].each do |path|
|
9
9
|
MetricFu.metrics_require { path }
|
10
10
|
end
|
11
|
-
|
11
|
+
%w(careful_array record).each do |path|
|
12
|
+
MetricFu.data_structures_require { path }
|
13
|
+
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
module MetricFu
|
16
|
+
class CodeIssue < DelegateClass(MetricFu::Record) #DelegateClass(Ruport::Data::Record)
|
17
|
+
include Comparable
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
# TODO: Yuck! 'stat_value' is a column for StatHotspot
|
20
|
+
EXCLUDED_COLUMNS =
|
21
|
+
FlogHotspot::COLUMNS +
|
22
|
+
SaikuroHotspot::COLUMNS +
|
23
|
+
['stat_value'] +
|
24
|
+
ChurnHotspot::COLUMNS +
|
25
|
+
ReekHotspot.new.columns.extend(MetricFu::CarefulArray).carefully_remove(['reek__type_name',
|
26
|
+
'reek__comparable_message']) +
|
27
|
+
FlayHotspot.new.columns.extend(MetricFu::CarefulArray).carefully_remove(['flay_matching_reason'])
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
def <=>(other)
|
30
|
+
spaceship_for_columns(self.attributes, other)
|
31
|
+
end
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
def ===(other)
|
34
|
+
self.hash_for(included_columns_hash, included_columns) == other.hash_for(included_columns_hash, included_columns)
|
35
|
+
end
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
def spaceship_for_columns(columns, other)
|
38
|
+
columns.each do |column|
|
39
|
+
equality = self[column].to_s <=> other[column].to_s
|
40
|
+
return equality if equality!=0
|
41
|
+
end
|
42
|
+
return 0
|
38
43
|
end
|
39
|
-
return 0
|
40
|
-
end
|
41
44
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
def hash_for(column_hash, columns)
|
46
|
+
@hashes ||= {}
|
47
|
+
# fetch would be cleaner, but slower
|
48
|
+
if @hashes.has_key?(column_hash)
|
49
|
+
@hashes[column_hash]
|
50
|
+
else
|
51
|
+
values = columns.map {|column| self[column]}
|
52
|
+
hash_for_columns = values.join('').hash
|
53
|
+
@hashes[column_hash]=hash_for_columns
|
54
|
+
hash_for_columns
|
55
|
+
end
|
52
56
|
end
|
53
|
-
end
|
54
57
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
+
def included_columns_hash
|
59
|
+
@included_columns_hash ||= included_columns.hash
|
60
|
+
end
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
+
def included_columns
|
63
|
+
@included_columns ||= self.attributes.extend(MetricFu::CarefulArray).carefully_remove(EXCLUDED_COLUMNS)
|
64
|
+
end
|
62
65
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
def find_counterpart_index_in(collection)
|
67
|
+
# each_with_index is cleaner, but it is slower and we
|
68
|
+
# spend a lot of time in this loop
|
69
|
+
index = 0
|
70
|
+
collection.each do |issue|
|
71
|
+
return index if self === issue
|
72
|
+
index += 1
|
73
|
+
end
|
74
|
+
return nil
|
70
75
|
end
|
71
|
-
return nil
|
72
|
-
end
|
73
76
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
77
|
+
def modifies?(other)
|
78
|
+
case self.metric
|
79
|
+
when :reek
|
80
|
+
#return false unless ["Large Class", "Long Method", "Long Parameter List"].include?(self.reek__type_name)
|
81
|
+
return false if self.reek__type_name != other.reek__type_name
|
82
|
+
self.reek__value != other.reek__value
|
83
|
+
when :flog
|
84
|
+
self.score != other.score
|
85
|
+
when :saikuro
|
86
|
+
self.complexity != other.complexity
|
87
|
+
when :stats
|
88
|
+
self.stat_value != other.stat_value
|
89
|
+
when :churn
|
90
|
+
self.times_changed != other.times_changed
|
91
|
+
when :flay
|
92
|
+
#self.flay_reason != other.flay_reason
|
93
|
+
# do nothing for now
|
94
|
+
when :roodi, :stats
|
95
|
+
# do nothing
|
96
|
+
else
|
97
|
+
raise ArgumentError, "Invalid metric type #{self.metric}"
|
98
|
+
end
|
95
99
|
end
|
96
|
-
end
|
97
100
|
|
101
|
+
end
|
98
102
|
end
|
@@ -12,12 +12,12 @@ module MetricFu
|
|
12
12
|
hash = table.group_by_metric
|
13
13
|
else
|
14
14
|
table.each do |row|
|
15
|
-
hash[row[column_name]] ||= Table.new(:column_names => row.attributes)
|
15
|
+
hash[row[column_name]] ||= MetricFu::Table.new(:column_names => row.attributes)
|
16
16
|
hash[row[column_name]] << row
|
17
17
|
end
|
18
18
|
end
|
19
19
|
if order
|
20
|
-
@arr = hash.sort_by
|
20
|
+
@arr = hash.sort_by(&order)
|
21
21
|
else
|
22
22
|
@arr = hash.to_a
|
23
23
|
end
|
@@ -1,106 +1,108 @@
|
|
1
|
-
%w(record).each do |path|
|
1
|
+
%w(record code_issue).each do |path|
|
2
2
|
MetricFu.data_structures_require { path }
|
3
3
|
end
|
4
4
|
|
5
|
-
|
5
|
+
module MetricFu
|
6
|
+
class Table
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def initialize(opts = {})
|
9
|
+
@rows = []
|
10
|
+
@columns = opts.fetch(:column_names)
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
@make_index = opts.fetch(:make_index) {true}
|
13
|
+
@metric_index = {}
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
def <<(row)
|
17
|
+
record = nil
|
18
|
+
if row.is_a?(MetricFu::Record) || row.is_a?(MetricFu::CodeIssue)
|
19
|
+
record = row
|
20
|
+
else
|
21
|
+
record = MetricFu::Record.new(row, @columns)
|
22
|
+
end
|
23
|
+
@rows << record
|
24
|
+
updated_key_index(record) if @make_index
|
21
25
|
end
|
22
|
-
@rows << record
|
23
|
-
updated_key_index(record) if @make_index
|
24
|
-
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
def each
|
28
|
+
@rows.each do |row|
|
29
|
+
yield row
|
30
|
+
end
|
29
31
|
end
|
30
|
-
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
def size
|
34
|
+
length
|
35
|
+
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
def length
|
38
|
+
@rows.length
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
def [](index)
|
42
|
+
@rows[index]
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
def column(column_name)
|
46
|
+
arr = []
|
47
|
+
@rows.each do |row|
|
48
|
+
arr << row[column_name]
|
49
|
+
end
|
50
|
+
arr
|
48
51
|
end
|
49
|
-
arr
|
50
|
-
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
def group_by_metric
|
54
|
+
@metric_index.to_a
|
55
|
+
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
def rows_with(conditions)
|
58
|
+
if optimized_conditions?(conditions)
|
59
|
+
optimized_select(conditions)
|
60
|
+
else
|
61
|
+
slow_select(conditions)
|
62
|
+
end
|
61
63
|
end
|
62
|
-
end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
65
|
+
def delete_at(index)
|
66
|
+
@rows.delete_at(index)
|
67
|
+
end
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
def to_a
|
70
|
+
@rows
|
71
|
+
end
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
def map
|
74
|
+
new_table = MetricFu::Table.new(:column_names => @columns)
|
75
|
+
@rows.map do |row|
|
76
|
+
new_table << (yield row)
|
77
|
+
end
|
78
|
+
new_table
|
76
79
|
end
|
77
|
-
new_table
|
78
|
-
end
|
79
80
|
|
80
|
-
|
81
|
+
private
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
83
|
+
def optimized_conditions?(conditions)
|
84
|
+
conditions.keys.length == 1 && conditions.keys.first.to_sym == :metric
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
def optimized_select(conditions)
|
88
|
+
metric = (conditions['metric'] || conditions[:metric]).to_s
|
89
|
+
@metric_index[metric].to_a.clone
|
90
|
+
end
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
def slow_select(conditions)
|
93
|
+
@rows.select do |row|
|
94
|
+
conditions.all? do |key, value|
|
95
|
+
row.has_key?(key.to_s) && row[key.to_s] == value
|
96
|
+
end
|
95
97
|
end
|
96
98
|
end
|
97
|
-
end
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
def updated_key_index(record)
|
101
|
+
if record.has_key?('metric')
|
102
|
+
@metric_index[record.metric] ||= MetricFu::Table.new(:column_names => @columns, :make_index => false)
|
103
|
+
@metric_index[record.metric] << record
|
104
|
+
end
|
103
105
|
end
|
104
|
-
end
|
105
106
|
|
107
|
+
end
|
106
108
|
end
|