metric_fu 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/HISTORY +13 -5
  2. data/README +2 -2
  3. data/Rakefile +1 -1
  4. data/TODO +3 -1
  5. data/lib/base/base_template.rb +16 -16
  6. data/lib/base/churn_analyzer.rb +3 -3
  7. data/lib/base/code_issue.rb +8 -8
  8. data/lib/base/configuration.rb +24 -22
  9. data/lib/base/flay_analyzer.rb +2 -2
  10. data/lib/base/flog_analyzer.rb +4 -4
  11. data/lib/base/generator.rb +21 -21
  12. data/lib/base/graph.rb +15 -10
  13. data/lib/base/line_numbers.rb +56 -55
  14. data/lib/base/location.rb +68 -66
  15. data/lib/base/metric_analyzer.rb +21 -21
  16. data/lib/base/ranking.rb +23 -22
  17. data/lib/base/rcov_analyzer.rb +3 -3
  18. data/lib/base/reek_analyzer.rb +12 -10
  19. data/lib/base/report.rb +9 -9
  20. data/lib/base/roodi_analyzer.rb +2 -2
  21. data/lib/base/saikuro_analyzer.rb +4 -4
  22. data/lib/base/scoring_strategies.rb +5 -5
  23. data/lib/base/stats_analyzer.rb +2 -2
  24. data/lib/base/table.rb +4 -4
  25. data/lib/generators/churn.rb +1 -1
  26. data/lib/generators/flay.rb +1 -1
  27. data/lib/generators/hotspots.rb +4 -4
  28. data/lib/generators/rails_best_practices.rb +1 -1
  29. data/lib/generators/rcov.rb +17 -17
  30. data/lib/generators/reek.rb +2 -2
  31. data/lib/generators/saikuro.rb +42 -42
  32. data/lib/generators/stats.rb +6 -6
  33. data/lib/graphs/engines/bluff.rb +1 -1
  34. data/lib/graphs/engines/gchart.rb +7 -7
  35. data/lib/graphs/flog_grapher.rb +3 -3
  36. data/lib/graphs/grapher.rb +1 -1
  37. data/lib/metric_fu.rb +2 -2
  38. data/lib/templates/awesome/churn.html.erb +1 -1
  39. data/lib/templates/awesome/css/integrity.css +0 -1
  40. data/lib/templates/awesome/flay.html.erb +2 -2
  41. data/lib/templates/awesome/flog.html.erb +2 -2
  42. data/lib/templates/awesome/hotspots.html.erb +4 -4
  43. data/lib/templates/awesome/index.html.erb +2 -2
  44. data/lib/templates/awesome/rails_best_practices.html.erb +1 -1
  45. data/lib/templates/awesome/rcov.html.erb +1 -1
  46. data/lib/templates/awesome/roodi.html.erb +1 -1
  47. data/lib/templates/awesome/saikuro.html.erb +3 -3
  48. data/lib/templates/awesome/stats.html.erb +1 -1
  49. data/lib/templates/standard/churn.html.erb +2 -2
  50. data/lib/templates/standard/default.css +4 -4
  51. data/lib/templates/standard/flay.html.erb +4 -4
  52. data/lib/templates/standard/flog.html.erb +1 -1
  53. data/lib/templates/standard/hotspots.html.erb +4 -4
  54. data/lib/templates/standard/index.html.erb +2 -2
  55. data/lib/templates/standard/rails_best_practices.html.erb +2 -2
  56. data/lib/templates/standard/rcov.html.erb +2 -2
  57. data/lib/templates/standard/reek.html.erb +1 -1
  58. data/lib/templates/standard/roodi.html.erb +2 -2
  59. data/lib/templates/standard/saikuro.html.erb +4 -4
  60. data/lib/templates/standard/stats.html.erb +2 -2
  61. data/spec/base/base_template_spec.rb +1 -1
  62. data/spec/base/configuration_spec.rb +36 -36
  63. data/spec/base/generator_spec.rb +10 -10
  64. data/spec/base/graph_spec.rb +41 -4
  65. data/spec/base/line_numbers_spec.rb +22 -22
  66. data/spec/base/report_spec.rb +9 -9
  67. data/spec/generators/churn_spec.rb +4 -4
  68. data/spec/generators/flay_spec.rb +31 -31
  69. data/spec/generators/flog_spec.rb +18 -18
  70. data/spec/generators/rails_best_practices_spec.rb +6 -6
  71. data/spec/generators/rcov_spec.rb +18 -18
  72. data/spec/generators/reek_spec.rb +10 -10
  73. data/spec/generators/roodi_spec.rb +2 -2
  74. data/spec/generators/saikuro_spec.rb +7 -7
  75. data/spec/generators/stats_spec.rb +6 -6
  76. data/spec/graphs/engines/gchart_spec.rb +8 -8
  77. data/spec/graphs/flog_grapher_spec.rb +8 -8
  78. data/spec/resources/line_numbers/foo.rb +7 -7
  79. data/spec/resources/line_numbers/module.rb +2 -2
  80. data/spec/resources/line_numbers/module_surrounds_class.rb +6 -6
  81. data/spec/resources/saikuro/index_cyclo.html +2 -2
  82. data/spec/resources/yml/20090630.yml +349 -349
  83. data/spec/resources/yml/metric_missing.yml +1 -1
  84. data/tasks/metric_fu.rake +4 -4
  85. metadata +4 -4
@@ -2,18 +2,18 @@ module MetricFu
2
2
 
3
3
  # = Generator
4
4
  #
5
- # The Generator class is an abstract class that provides the
5
+ # The Generator class is an abstract class that provides the
6
6
  # skeleton for producing different types of metrics.
7
7
  #
8
- # It drives the production of the metrics through a template
8
+ # It drives the production of the metrics through a template
9
9
  # method - #generate_report(options={}). This method calls
10
10
  # #emit, #analyze and #to_h in order to produce the metrics.
11
11
  #
12
12
  # To implement a concrete class to generate a metric, therefore,
13
- # the class must implement those three methods.
13
+ # the class must implement those three methods.
14
14
  #
15
- # * #emit should take care of running the metric tool and
16
- # gathering its output.
15
+ # * #emit should take care of running the metric tool and
16
+ # gathering its output.
17
17
  # * #analyze should take care of manipulating the output from
18
18
  # #emit and making it possible to store it in a programmatic way.
19
19
  # * #to_h should provide a hash representation of the output from
@@ -37,9 +37,9 @@ module MetricFu
37
37
  create_output_dir_if_missing
38
38
  create_data_dir_if_missing
39
39
  end
40
-
41
- # Creates a new generator and returns the output of the
42
- # #generate_report method. This is the typical way to
40
+
41
+ # Creates a new generator and returns the output of the
42
+ # #generate_report method. This is the typical way to
43
43
  # generate a new MetricFu report. For more information see
44
44
  # the #generate_report instance method.
45
45
  #
@@ -66,27 +66,27 @@ module MetricFu
66
66
  def self.class_name
67
67
  self.to_s.split('::').last.downcase
68
68
  end
69
-
69
+
70
70
  # Returns the directory where the Generator will write any output
71
71
  def self.metric_directory
72
- File.join(MetricFu.scratch_directory, class_name)
72
+ File.join(MetricFu.scratch_directory, class_name)
73
73
  end
74
74
 
75
75
  def create_metric_dir_if_missing #:nodoc:
76
76
  unless File.directory?(metric_directory)
77
- FileUtils.mkdir_p(metric_directory, :verbose => false)
77
+ FileUtils.mkdir_p(metric_directory, :verbose => false)
78
78
  end
79
79
  end
80
-
80
+
81
81
  def create_output_dir_if_missing #:nodoc:
82
82
  unless File.directory?(MetricFu.output_directory)
83
- FileUtils.mkdir_p(MetricFu.output_directory, :verbose => false)
83
+ FileUtils.mkdir_p(MetricFu.output_directory, :verbose => false)
84
84
  end
85
85
  end
86
-
86
+
87
87
  def create_data_dir_if_missing #:nodoc:
88
88
  unless File.directory?(MetricFu.data_directory)
89
- FileUtils.mkdir_p(MetricFu.data_directory, :verbose => false)
89
+ FileUtils.mkdir_p(MetricFu.data_directory, :verbose => false)
90
90
  end
91
91
  end
92
92
 
@@ -103,7 +103,7 @@ module MetricFu
103
103
  end
104
104
  paths - files_to_remove
105
105
  end
106
-
106
+
107
107
  # Defines some hook methods for the concrete classes to hook into.
108
108
  %w[emit analyze].each do |meth|
109
109
  define_method("before_#{meth}".to_sym) {}
@@ -132,13 +132,13 @@ module MetricFu
132
132
 
133
133
  def round_to_tenths(decimal)
134
134
  decimal = 0.0 if decimal.to_s.eql?('NaN')
135
- (decimal * 10).round / 10.0
135
+ (decimal * 10).round / 10.0
136
136
  end
137
137
 
138
138
  def emit #:nodoc:
139
139
  raise <<-EOF
140
140
  This method must be implemented by a concrete class descending
141
- from Generator. See generator class documentation for more
141
+ from Generator. See generator class documentation for more
142
142
  information.
143
143
  EOF
144
144
  end
@@ -146,15 +146,15 @@ module MetricFu
146
146
  def analyze #:nodoc:
147
147
  raise <<-EOF
148
148
  This method must be implemented by a concrete class descending
149
- from Generator. See generator class documentation for more
149
+ from Generator. See generator class documentation for more
150
150
  information.
151
151
  EOF
152
152
  end
153
-
153
+
154
154
  def to_graph #:nodoc:
155
155
  raise <<-EOF
156
156
  This method must be implemented by a concrete class descending
157
- from Generator. See generator class documentation for more
157
+ from Generator. See generator class documentation for more
158
158
  information.
159
159
  EOF
160
160
  end
@@ -5,35 +5,40 @@ module MetricFu
5
5
  end
6
6
 
7
7
  class Graph
8
-
8
+
9
9
  attr_accessor :clazz
10
-
10
+
11
11
  def initialize
12
12
  self.clazz = []
13
13
  end
14
-
14
+
15
15
  def add(graph_type, graph_engine)
16
16
  grapher_name = graph_type.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } + graph_engine.to_s.capitalize + "Grapher"
17
17
  self.clazz.push MetricFu.const_get(grapher_name).new
18
18
  end
19
-
20
-
19
+
20
+
21
21
  def generate
22
22
  return if self.clazz.empty?
23
23
  puts "Generating graphs"
24
24
  Dir[File.join(MetricFu.data_directory, '*.yml')].sort.each do |metric_file|
25
25
  puts "Generating graphs for #{metric_file}"
26
- date = metric_file.split('/')[3].split('.')[0]
27
- y, m, d = date[0..3].to_i, date[4..5].to_i, date[6..7].to_i
26
+ date_parts = year_month_day_from_filename(metric_file)
28
27
  metrics = YAML::load(File.open(metric_file))
29
-
28
+
30
29
  self.clazz.each do |grapher|
31
- grapher.get_metrics(metrics, "#{m}/#{d}")
30
+ grapher.get_metrics(metrics, "#{date_parts[:m]}/#{date_parts[:d]}")
32
31
  end
33
32
  end
34
33
  self.clazz.each do |grapher|
35
34
  grapher.graph!
36
35
  end
37
36
  end
37
+
38
+ private
39
+ def year_month_day_from_filename(path_to_file_with_date)
40
+ date = path_to_file_with_date.match(/\/(\d+).yml$/)[1]
41
+ {:y => date[0..3].to_i, :m => date[4..5].to_i, :d => date[6..7].to_i}
42
+ end
38
43
  end
39
- end
44
+ end
@@ -1,65 +1,66 @@
1
1
  require 'ruby_parser'
2
+ module MetricFu
3
+ class LineNumbers
2
4
 
3
- class LineNumbers
5
+ def initialize(contents)
6
+ rp = RubyParser.new
7
+ file_sexp = rp.parse(contents)
8
+ @locations = {}
9
+ case file_sexp[0]
10
+ when :class
11
+ process_class(file_sexp)
12
+ when :module
13
+ process_module(file_sexp)
14
+ when :block
15
+ file_sexp.each_of_type(:class) { |sexp| process_class(sexp) }
16
+ else
17
+ end
18
+ end
4
19
 
5
- def initialize(contents)
6
- rp = RubyParser.new
7
- file_sexp = rp.parse(contents)
8
- @locations = {}
9
- case file_sexp[0]
10
- when :class
11
- process_class(file_sexp)
12
- when :module
13
- process_module(file_sexp)
14
- when :block
15
- file_sexp.each_of_type(:class) { |sexp| process_class(sexp) }
16
- else
20
+ def in_method? line_number
21
+ !!@locations.detect do |method_name, line_number_range|
22
+ line_number_range.include?(line_number)
23
+ end
17
24
  end
18
- end
19
-
20
- def in_method? line_number
21
- !!@locations.detect do |method_name, line_number_range|
22
- line_number_range.include?(line_number)
25
+
26
+ def method_at_line line_number
27
+ found_method_and_range = @locations.detect do |method_name, line_number_range|
28
+ line_number_range.include?(line_number)
29
+ end
30
+ return nil unless found_method_and_range
31
+ found_method_and_range.first
23
32
  end
24
- end
25
-
26
- def method_at_line line_number
27
- found_method_and_range = @locations.detect do |method_name, line_number_range|
28
- line_number_range.include?(line_number)
33
+
34
+ private
35
+
36
+ def process_module(sexp)
37
+ module_name = sexp[1]
38
+ sexp.each_of_type(:class) do |sexp|
39
+ process_class(sexp, module_name)
40
+ hide_methods_from_next_round(sexp)
41
+ end
42
+ process_class(sexp)
29
43
  end
30
- return nil unless found_method_and_range
31
- found_method_and_range.first
32
- end
33
-
34
- private
35
-
36
- def process_module(sexp)
37
- module_name = sexp[1]
38
- sexp.each_of_type(:class) do |sexp|
39
- process_class(sexp, module_name)
40
- hide_methods_from_next_round(sexp)
44
+
45
+ def process_class(sexp, module_name=nil)
46
+ class_name = sexp[1]
47
+ process_class_self_blocks(sexp, class_name)
48
+ module_name_string = module_name ? "#{module_name}::" : nil
49
+ sexp.each_of_type(:defn) { |s| @locations["#{module_name_string}#{class_name}##{s[1]}"] = (s.line)..(s.last.line) }
50
+ sexp.each_of_type(:defs) { |s| @locations["#{module_name_string}#{class_name}::#{s[2]}"] = (s.line)..(s.last.line) }
41
51
  end
42
- process_class(sexp)
43
- end
44
-
45
- def process_class(sexp, module_name=nil)
46
- class_name = sexp[1]
47
- process_class_self_blocks(sexp, class_name)
48
- module_name_string = module_name ? "#{module_name}::" : nil
49
- sexp.each_of_type(:defn) { |s| @locations["#{module_name_string}#{class_name}##{s[1]}"] = (s.line)..(s.last.line) }
50
- sexp.each_of_type(:defs) { |s| @locations["#{module_name_string}#{class_name}::#{s[2]}"] = (s.line)..(s.last.line) }
51
- end
52
-
53
- def process_class_self_blocks(sexp, class_name)
54
- sexp.each_of_type(:sclass) do |sexp_in_class_self_block|
55
- sexp_in_class_self_block.each_of_type(:defn) { |s| @locations["#{class_name}::#{s[1]}"] = (s.line)..(s.last.line) }
56
- hide_methods_from_next_round(sexp_in_class_self_block)
52
+
53
+ def process_class_self_blocks(sexp, class_name)
54
+ sexp.each_of_type(:sclass) do |sexp_in_class_self_block|
55
+ sexp_in_class_self_block.each_of_type(:defn) { |s| @locations["#{class_name}::#{s[1]}"] = (s.line)..(s.last.line) }
56
+ hide_methods_from_next_round(sexp_in_class_self_block)
57
+ end
57
58
  end
59
+
60
+ def hide_methods_from_next_round(sexp)
61
+ sexp.find_and_replace_all(:defn, :ignore_me)
62
+ sexp.find_and_replace_all(:defs, :ignore_me)
63
+ end
64
+
58
65
  end
59
-
60
- def hide_methods_from_next_round(sexp)
61
- sexp.find_and_replace_all(:defn, :ignore_me)
62
- sexp.find_and_replace_all(:defs, :ignore_me)
63
- end
64
-
65
66
  end
@@ -1,83 +1,85 @@
1
- class Location
2
- include Comparable
1
+ module MetricFu
2
+ class Location
3
+ include Comparable
3
4
 
4
- attr_accessor :class_name, :method_name, :file_path, :simple_method_name, :hash
5
+ attr_accessor :class_name, :method_name, :file_path, :simple_method_name, :hash
5
6
 
6
- def self.get(file_path, class_name, method_name)
7
- # This could be more 'confident' using Maybe, but we want it to be as fast as possible
8
- file_path_copy = file_path == nil ? nil : file_path.clone
9
- class_name_copy = class_name == nil ? nil : class_name.clone
10
- method_name_copy = method_name == nil ? nil : method_name.clone
11
- key = [file_path_copy, class_name_copy, method_name_copy]
12
- @@locations ||= {}
13
- if @@locations.has_key?(key)
14
- @@locations[key]
15
- else
16
- location = self.new(file_path_copy, class_name_copy, method_name_copy)
17
- @@locations[key] = location
18
- location.freeze # we cache a lot of method call results, so we want location to be immutable
19
- location
7
+ def self.get(file_path, class_name, method_name)
8
+ # This could be more 'confident' using Maybe, but we want it to be as fast as possible
9
+ file_path_copy = file_path == nil ? nil : file_path.clone
10
+ class_name_copy = class_name == nil ? nil : class_name.clone
11
+ method_name_copy = method_name == nil ? nil : method_name.clone
12
+ key = [file_path_copy, class_name_copy, method_name_copy]
13
+ @@locations ||= {}
14
+ if @@locations.has_key?(key)
15
+ @@locations[key]
16
+ else
17
+ location = self.new(file_path_copy, class_name_copy, method_name_copy)
18
+ @@locations[key] = location
19
+ location.freeze # we cache a lot of method call results, so we want location to be immutable
20
+ location
21
+ end
20
22
  end
21
- end
22
23
 
23
- def initialize(file_path, class_name, method_name)
24
- @file_path = file_path
25
- @class_name = class_name
26
- @method_name = method_name
27
- @simple_method_name = @method_name.sub(@class_name,'') unless @method_name == nil
28
- @hash = [@file_path, @class_name, @method_name].hash
29
- end
24
+ def initialize(file_path, class_name, method_name)
25
+ @file_path = file_path
26
+ @class_name = class_name
27
+ @method_name = method_name
28
+ @simple_method_name = @method_name.sub(@class_name,'') unless @method_name == nil
29
+ @hash = [@file_path, @class_name, @method_name].hash
30
+ end
30
31
 
31
- # TODO - we need this method (and hash accessor above) as a temporary hack where we're using Location as a hash key
32
- def eql?(other)
33
- [self.file_path.to_s, self.class_name.to_s, self.method_name.to_s] == [other.file_path.to_s, other.class_name.to_s, other.method_name.to_s]
34
- end
32
+ # TODO - we need this method (and hash accessor above) as a temporary hack where we're using Location as a hash key
33
+ def eql?(other)
34
+ [self.file_path.to_s, self.class_name.to_s, self.method_name.to_s] == [other.file_path.to_s, other.class_name.to_s, other.method_name.to_s]
35
+ end
36
+ # END we need these methods as a temporary hack where we're using Location as a hash key
35
37
 
36
- # END we need these methods as a temporary hack where we're using Location as a hash key
37
-
38
- def self.for(class_or_method_name)
39
- class_or_method_name = strip_modules(class_or_method_name)
40
- if(class_or_method_name)
41
- begin
42
- match = class_or_method_name.match(/(.*)((\.|\#|\:\:[a-z])(.+))/)
43
- rescue => error
44
- #new error during port to metric_fu occasionally a unintialized
45
- #MatchData object shows up here. Not expected.
46
- match = nil
47
- end
38
+ def self.for(class_or_method_name)
39
+ class_or_method_name = strip_modules(class_or_method_name)
40
+ if(class_or_method_name)
41
+ begin
42
+ match = class_or_method_name.match(/(.*)((\.|\#|\:\:[a-z])(.+))/)
43
+ rescue => error
44
+ #new error during port to metric_fu occasionally a unintialized
45
+ #MatchData object shows up here. Not expected.
46
+ match = nil
47
+ end
48
48
 
49
- # reek reports the method with :: not # on modules like
50
- # module ApplicationHelper \n def signed_in?, convert it so it records correctly
51
- # but classes have to start with a capital letter... HACK for REEK bug, reported underlying issue to REEK
52
- if(match)
53
- class_name = strip_modules(match[1])
54
- method_name = class_or_method_name.gsub(/\:\:/,"#")
49
+ # reek reports the method with :: not # on modules like
50
+ # module ApplicationHelper \n def signed_in?, convert it so it records correctly
51
+ # but classes have to start with a capital letter... HACK for REEK bug, reported underlying issue to REEK
52
+ if(match)
53
+ class_name = strip_modules(match[1])
54
+ method_name = class_or_method_name.gsub(/\:\:/,"#")
55
+ else
56
+ class_name = strip_modules(class_or_method_name)
57
+ method_name = nil
58
+ end
55
59
  else
56
- class_name = strip_modules(class_or_method_name)
60
+ class_name = nil
57
61
  method_name = nil
58
62
  end
59
- else
60
- class_name = nil
61
- method_name = nil
63
+ self.get(nil, class_name, method_name)
62
64
  end
63
- self.get(nil, class_name, method_name)
64
- end
65
65
 
66
- def <=>(other)
67
- [self.file_path.to_s, self.class_name.to_s, self.method_name.to_s] <=> [other.file_path.to_s, other.class_name.to_s, other.method_name.to_s]
68
- end
66
+ def <=>(other)
67
+ [self.file_path.to_s, self.class_name.to_s, self.method_name.to_s] <=> [other.file_path.to_s, other.class_name.to_s, other.method_name.to_s]
68
+ end
69
69
 
70
- private
70
+ private
71
+
72
+ def self.strip_modules(class_or_method_name)
73
+ # reek reports the method with :: not # on modules like
74
+ # module ApplicationHelper \n def signed_in?, convert it so it records correctly
75
+ # but classes have to start with a capital letter... HACK for REEK bug, reported underlying issue to REEK
76
+ if(class_or_method_name=~/\:\:[A-Z]/)
77
+ class_or_method_name.split("::").last
78
+ else
79
+ class_or_method_name
80
+ end
71
81
 
72
- def self.strip_modules(class_or_method_name)
73
- # reek reports the method with :: not # on modules like
74
- # module ApplicationHelper \n def signed_in?, convert it so it records correctly
75
- # but classes have to start with a capital letter... HACK for REEK bug, reported underlying issue to REEK
76
- if(class_or_method_name=~/\:\:[A-Z]/)
77
- class_or_method_name.split("::").last
78
- else
79
- class_or_method_name
80
82
  end
81
- end
82
83
 
84
+ end
83
85
  end
@@ -13,9 +13,9 @@ class MetricAnalyzer
13
13
  else
14
14
  @yaml = yaml
15
15
  end
16
- @file_ranking = Ranking.new
17
- @class_ranking = Ranking.new
18
- @method_ranking = Ranking.new
16
+ @file_ranking = MetricFu::Ranking.new
17
+ @class_ranking = MetricFu::Ranking.new
18
+ @method_ranking = MetricFu::Ranking.new
19
19
  rankings = [@file_ranking, @class_ranking, @method_ranking]
20
20
 
21
21
  tool_analyzers = [ReekAnalyzer.new, RoodiAnalyzer.new,
@@ -27,14 +27,14 @@ class MetricAnalyzer
27
27
  columns = COMMON_COLUMNS + GRANULARITIES + tool_analyzers.map{|analyzer| analyzer.columns}.flatten
28
28
 
29
29
  @table = make_table(columns)
30
-
30
+
31
31
  # These tables are an optimization. They contain subsets of the master table.
32
32
  # TODO - these should be pushed into the Table class now
33
33
  @tool_tables = make_table_hash(columns)
34
34
  @file_tables = make_table_hash(columns)
35
35
  @class_tables = make_table_hash(columns)
36
36
  @method_tables = make_table_hash(columns)
37
-
37
+
38
38
  tool_analyzers.each do |analyzer|
39
39
  analyzer.generate_records(@yaml[analyzer.name], @table)
40
40
  end
@@ -62,11 +62,11 @@ class MetricAnalyzer
62
62
  first_row = sub_table[0]
63
63
  case item
64
64
  when :class
65
- Location.get(first_row.file_path, first_row.class_name, nil)
65
+ MetricFu::Location.get(first_row.file_path, first_row.class_name, nil)
66
66
  when :method
67
- Location.get(first_row.file_path, first_row.class_name, first_row.method_name)
67
+ MetricFu::Location.get(first_row.file_path, first_row.class_name, first_row.method_name)
68
68
  when :file
69
- Location.get(first_row.file_path, nil, nil)
69
+ MetricFu::Location.get(first_row.file_path, nil, nil)
70
70
  else
71
71
  raise ArgumentError, "Item must be :class, :method, or :file"
72
72
  end
@@ -147,7 +147,7 @@ class MetricAnalyzer
147
147
 
148
148
  def fix_row_file_path!(row)
149
149
  # We know that Saikuro rows are broken
150
- next unless row['metric'] == :saikuro
150
+ # next unless row['metric'] == :saikuro
151
151
  key = [row['class_name'], row['method_name']]
152
152
  current_file_path = row['file_path'].to_s
153
153
  correct_file_path = @class_and_method_to_file[key]
@@ -155,7 +155,7 @@ class MetricAnalyzer
155
155
  row['file_path'] = correct_file_path
156
156
  else
157
157
  # There wasn't an exact match, so we can do a substring match
158
- matching_file_path = file_paths.detect {|file_path|
158
+ matching_file_path = file_paths.detect {|file_path|
159
159
  file_path!=nil && file_path.include?(current_file_path)
160
160
  }
161
161
  if(matching_file_path)
@@ -180,32 +180,32 @@ class MetricAnalyzer
180
180
  raise ArgumentError, "Invalid column name #{column_name}"
181
181
  end
182
182
  end
183
-
183
+
184
184
  def calculate_metric_scores(granularity, analyzer)
185
- metric_ranking = Ranking.new
185
+ metric_ranking = MetricFu::Ranking.new
186
186
  metric_violations = @tool_tables[analyzer.name]
187
187
  metric_violations.each do |row|
188
188
  location = row[granularity]
189
189
  metric_ranking[location] ||= []
190
190
  metric_ranking[location] << analyzer.map(row)
191
191
  end
192
-
192
+
193
193
  metric_ranking.each do |item, scores|
194
194
  metric_ranking[item] = analyzer.reduce(scores)
195
195
  end
196
-
196
+
197
197
  metric_ranking
198
198
  end
199
199
 
200
200
  def add_to_master_ranking(master_ranking, metric_ranking, analyzer)
201
201
  metric_ranking.each do |item, _|
202
202
  master_ranking[item] ||= 0
203
- master_ranking[item] += analyzer.score(metric_ranking, item)
203
+ master_ranking[item] += analyzer.score(metric_ranking, item) # scaling? Do we just add in the raw score?
204
204
  end
205
205
  end
206
206
 
207
207
  def most_common_column(column_name, size)
208
- #grouping = Ruport::Data::Grouping.new(@table,
208
+ #grouping = Ruport::Data::Grouping.new(@table,
209
209
  # :by => column_name,
210
210
  # :order => lambda { |g| -g.size})
211
211
  get_grouping(@table, :by => column_name, :order => lambda {|g| -g.size})
@@ -223,7 +223,7 @@ class MetricAnalyzer
223
223
  return values
224
224
  end
225
225
  end
226
-
226
+
227
227
  # TODO: As we get fancier, the presenter should
228
228
  # be its own class, not just a method with a long
229
229
  # case statement
@@ -246,7 +246,7 @@ class MetricAnalyzer
246
246
  "found #{occurences} code duplications"
247
247
  when :rcov
248
248
  average_code_uncoverage = get_mean(group.column("percentage_uncovered"))
249
- "#{"average " if occurences > 1}uncovered code is %.1f%" % average_code_uncoverage
249
+ "#{"average " if occurences > 1}uncovered code is %.1f%" % average_code_uncoverage
250
250
  else
251
251
  raise AnalysisError, "Unknown metric #{metric}"
252
252
  end
@@ -320,13 +320,13 @@ class MetricAnalyzer
320
320
  sum = collection.inject( nil ) { |sum,x| sum ? sum+x : x }
321
321
  (sum.to_f / collection_length.to_f)
322
322
  end
323
-
323
+
324
324
  end
325
325
 
326
326
  class Record
327
327
 
328
328
  attr_reader :data
329
-
329
+
330
330
  def initialize(data, columns)
331
331
  @data = data
332
332
  @columns = columns
@@ -380,7 +380,7 @@ class Grouping
380
380
  end
381
381
  end
382
382
  if order
383
- @arr = hash.sort_by &order
383
+ @arr = hash.sort_by &order
384
384
  else
385
385
  @arr = hash.to_a
386
386
  end