metric_fu 2.1.3.4 → 2.1.3.5
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.
- 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
|
-
[](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
|
-
[](https://codeclimate.com/github/
|
25
|
+
[](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
|