metric_fu 4.3.1 → 4.4.0

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.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.metrics +55 -26
  3. data/.travis.yml +4 -1
  4. data/AUTHORS +12 -0
  5. data/Gemfile +1 -0
  6. data/HISTORY.md +24 -0
  7. data/README.md +27 -22
  8. data/checksum/metric_fu-4.3.1.gem.sha512 +1 -0
  9. data/checksum/metric_fu-4.4.0.gem.sha512 +1 -0
  10. data/lib/metric_fu.rb +28 -79
  11. data/lib/metric_fu/cli/helper.rb +1 -1
  12. data/lib/metric_fu/cli/parser.rb +1 -1
  13. data/lib/metric_fu/configuration.rb +104 -150
  14. data/lib/metric_fu/environment.rb +88 -0
  15. data/lib/metric_fu/formatter.rb +23 -0
  16. data/lib/metric_fu/formatter/html.rb +12 -9
  17. data/lib/metric_fu/initial_requires.rb +1 -0
  18. data/lib/metric_fu/io.rb +60 -1
  19. data/lib/metric_fu/load_files.rb +4 -2
  20. data/lib/metric_fu/loader.rb +62 -0
  21. data/lib/metric_fu/metric.rb +102 -0
  22. data/lib/metric_fu/metrics/base_template.rb +15 -9
  23. data/lib/metric_fu/metrics/cane/cane.rb +9 -5
  24. data/lib/metric_fu/metrics/cane/init.rb +35 -13
  25. data/lib/metric_fu/metrics/churn/churn.rb +5 -1
  26. data/lib/metric_fu/metrics/churn/init.rb +24 -4
  27. data/lib/metric_fu/metrics/flay/flay.rb +7 -3
  28. data/lib/metric_fu/metrics/flay/init.rb +29 -13
  29. data/lib/metric_fu/metrics/flay/template_awesome/flay.html.erb +1 -1
  30. data/lib/metric_fu/metrics/flog/flog.rb +14 -38
  31. data/lib/metric_fu/metrics/flog/init.rb +30 -7
  32. data/lib/metric_fu/metrics/generator.rb +21 -6
  33. data/lib/metric_fu/metrics/graph.rb +2 -2
  34. data/lib/metric_fu/metrics/hotspots/hotspots.rb +5 -1
  35. data/lib/metric_fu/metrics/hotspots/init.rb +21 -5
  36. data/lib/metric_fu/metrics/rails_best_practices/init.rb +29 -5
  37. data/lib/metric_fu/metrics/rails_best_practices/rails_best_practices.rb +20 -27
  38. data/lib/metric_fu/metrics/rails_best_practices/template_awesome/rails_best_practices.html.erb +1 -1
  39. data/lib/metric_fu/metrics/rcov/init.rb +40 -15
  40. data/lib/metric_fu/metrics/rcov/rcov.rb +15 -10
  41. data/lib/metric_fu/metrics/reek/init.rb +25 -6
  42. data/lib/metric_fu/metrics/reek/reek.rb +52 -31
  43. data/lib/metric_fu/metrics/reek/template_awesome/reek.html.erb +1 -1
  44. data/lib/metric_fu/metrics/roodi/init.rb +25 -6
  45. data/lib/metric_fu/metrics/roodi/roodi.rb +7 -3
  46. data/lib/metric_fu/metrics/saikuro/init.rb +22 -6
  47. data/lib/metric_fu/metrics/saikuro/saikuro.rb +8 -3
  48. data/lib/metric_fu/metrics/stats/init.rb +28 -5
  49. data/lib/metric_fu/metrics/stats/stats.rb +24 -6
  50. data/lib/metric_fu/metrics/stats/template_awesome/stats.html.erb +2 -2
  51. data/lib/metric_fu/parser_ext.rb +15 -0
  52. data/lib/metric_fu/reporting/graphs/engines/gchart.rb +1 -1
  53. data/lib/metric_fu/reporting/graphs/engines/init.rb +18 -4
  54. data/lib/metric_fu/reporting/graphs/grapher.rb +1 -1
  55. data/lib/metric_fu/reporting/result.rb +13 -6
  56. data/lib/metric_fu/reporting/templates/awesome/awesome_template.rb +1 -1
  57. data/lib/metric_fu/run.rb +7 -10
  58. data/lib/metric_fu/sexp_ext.rb +11 -0
  59. data/lib/metric_fu/version.rb +1 -1
  60. data/metric_fu.gemspec +23 -20
  61. data/spec/cli/helper_spec.rb +5 -16
  62. data/spec/metric_fu/configuration_spec.rb +62 -88
  63. data/spec/metric_fu/formatter/html_spec.rb +26 -16
  64. data/spec/metric_fu/formatter/yaml_spec.rb +2 -2
  65. data/spec/metric_fu/metric_spec.rb +50 -0
  66. data/spec/metric_fu/metrics/base_template_spec.rb +9 -7
  67. data/spec/metric_fu/metrics/cane/cane_spec.rb +19 -24
  68. data/spec/metric_fu/metrics/churn/churn_spec.rb +8 -8
  69. data/spec/metric_fu/metrics/flay/flay_spec.rb +7 -13
  70. data/spec/metric_fu/metrics/flog/flog_spec.rb +63 -58
  71. data/spec/metric_fu/metrics/generator_spec.rb +4 -0
  72. data/spec/metric_fu/metrics/hotspots/hotspots_spec.rb +7 -7
  73. data/spec/metric_fu/metrics/rails_best_practices/rails_best_practices_spec.rb +14 -33
  74. data/spec/metric_fu/metrics/rcov/rcov_spec.rb +17 -18
  75. data/spec/metric_fu/metrics/reek/reek_spec.rb +9 -10
  76. data/spec/metric_fu/metrics/roodi/roodi_spec.rb +5 -11
  77. data/spec/metric_fu/metrics/saikuro/saikuro_spec.rb +15 -14
  78. data/spec/metric_fu/metrics/stats/stats_spec.rb +5 -6
  79. data/spec/metric_fu/reporting/graphs/engines/bluff_spec.rb +2 -3
  80. data/spec/metric_fu/reporting/graphs/engines/gchart_spec.rb +12 -9
  81. data/spec/metric_fu/reporting/result_spec.rb +3 -3
  82. data/spec/run_spec.rb +45 -29
  83. data/spec/spec_helper.rb +7 -0
  84. data/spec/support/helper_methods.rb +9 -0
  85. data/spec/support/suite.rb +17 -11
  86. metadata +59 -56
  87. data/bin/mf-rails_best_practices +0 -9
  88. data/bin/mf-stats +0 -7
@@ -1,7 +1,31 @@
1
- MetricFu::Configuration.run do |config|
2
- if config.rails?
3
- config.add_metric(:rails_best_practices)
4
- config.add_graph(:rails_best_practices)
5
- config.configure_metric(:rails_best_practices, {})
1
+ module MetricFu
2
+ class MetricRailsBestPractices < Metric
3
+
4
+ def name
5
+ :rails_best_practices
6
+ end
7
+
8
+ def default_run_options
9
+ {}
10
+ end
11
+
12
+ def has_graph?
13
+ true
14
+ end
15
+
16
+ def enable
17
+ if MetricFu.configuration.supports_ripper?
18
+ super if MetricFu.configuration.rails?
19
+ else
20
+ MetricFu.configuration.mf_debug("Rails Best Practices is only available in MRI 1.9. It requires ripper")
21
+ end
22
+ end
23
+
24
+ def activate
25
+ activate_library('rails_best_practices')
26
+ activate_library('metric_fu/sexp_ext')
27
+ super
28
+ end
29
+
6
30
  end
7
31
  end
@@ -1,36 +1,29 @@
1
1
  module MetricFu
2
- class RailsBestPractices < Generator
2
+ class RailsBestPracticesGenerator < Generator
3
+
4
+ def self.metric
5
+ :rails_best_practices
6
+ end
7
+
3
8
  def emit
4
- command = %Q(mf-rails_best_practices --without-color .)
5
- mf_debug "** #{command}"
6
- @output = `#{command}`
9
+ mf_debug "** Rails Best Practices"
10
+ path = '.'
11
+ analyzer = ::RailsBestPractices::Analyzer.new(path, { 'silent' => true })
12
+ analyzer.analyze
13
+ @output = analyzer.errors
7
14
  end
8
15
 
9
16
  def analyze
10
- @matches = @output.chomp.split("\n").map{|m| m.split(" - ") }
11
- total = @matches.pop
12
- cleanup_color_switches(total.first)
13
-
14
- 2.times { @matches.pop } # ignore wiki link
15
- @matches.reject! {|array| array.empty? }
16
- @matches.map! do |match|
17
- file, line = match[0].split(':')
18
- problem = match[1]
19
-
20
- cleanup_color_switches(file)
21
- cleanup_color_switches(problem)
22
-
23
- file.gsub!(/^\.\//, '')
24
-
25
- {:file => file, :line => line, :problem => problem}
17
+ @problems = @output.collect do |problem|
18
+ {
19
+ :file => problem.filename,
20
+ :line => problem.line_number,
21
+ :problem => problem.message,
22
+ :url => problem.url
23
+ }
26
24
  end
27
- @rails_best_practices_results = {:total => total, :problems => @matches}
28
- end
29
-
30
- def cleanup_color_switches(str)
31
- return if str.nil?
32
- str.gsub!(%r{^\e\[3[1|2]m}, '')
33
- str.gsub!(%r{\e\[0m$}, '')
25
+ total = ["Found #{@problems.count} errors."]
26
+ @rails_best_practices_results = {:total => total, :problems => @problems}
34
27
  end
35
28
 
36
29
  def to_h
@@ -19,7 +19,7 @@
19
19
  <% @rails_best_practices[:problems].each do |problem| %>
20
20
  <tr class='<%= cycle("light", "dark", count) %>'>
21
21
  <td><%= link_to_filename(problem[:file], problem[:line]) %></td>
22
- <td><%= problem[:problem] %></td>
22
+ <td><a href =<%= problem[:url] %>><%= problem[:problem] %></a></td>
23
23
  </tr>
24
24
  <% count += 1 %>
25
25
  <% end %>
@@ -1,20 +1,45 @@
1
- MetricFu::Configuration.run do |config|
2
- config.add_metric(:rcov)
3
- config.add_graph(:rcov)
4
- rcov_opts = [
5
- "--sort coverage",
6
- "--no-html",
7
- "--text-coverage",
8
- "--no-color",
9
- "--profile",
10
- "--exclude-only '.*'",
11
- '--include-file "\Aapp,\Alib"'
12
- ]
13
- rcov_opts << "-Ispec" if File.exist?("spec")
14
- config.configure_metric(:rcov,
1
+ module MetricFu
2
+ class MetricRcov < Metric
3
+
4
+ def name
5
+ :rcov
6
+ end
7
+
8
+ def default_run_options
15
9
  { :environment => 'test',
16
10
  :test_files => Dir['{spec,test}/**/*_{spec,test}.rb'],
17
11
  :rcov_opts => rcov_opts,
18
12
  :external => nil
19
- })
13
+ }
14
+ end
15
+
16
+ def has_graph?
17
+ true
18
+ end
19
+
20
+ def enable
21
+ MetricFu.configuration.mf_debug("rcov is not available. See README")
22
+ end
23
+
24
+ def activate
25
+ super
26
+ end
27
+
28
+ private
29
+
30
+ def rcov_opts
31
+ rcov_opts = [
32
+ "--sort coverage",
33
+ "--no-html",
34
+ "--text-coverage",
35
+ "--no-color",
36
+ "--profile",
37
+ "--exclude-only '.*'",
38
+ '--include-file "\Aapp,\Alib"'
39
+ ]
40
+ rcov_opts << "-Ispec" if File.exist?("spec")
41
+ rcov_opts
42
+ end
43
+
44
+ end
20
45
  end
@@ -1,10 +1,15 @@
1
1
  require 'enumerator'
2
+ require 'fileutils'
2
3
 
3
4
  module MetricFu
4
5
 
5
- class Rcov < Generator
6
+ class RcovGenerator < Generator
6
7
  NEW_FILE_MARKER = /^={80}$/.freeze
7
8
 
9
+ def self.metric
10
+ :rcov
11
+ end
12
+
8
13
  class Line
9
14
  attr_accessor :content, :was_run
10
15
 
@@ -20,7 +25,7 @@ module MetricFu
20
25
 
21
26
  def emit
22
27
  if run_rcov?
23
- mf_debug "** Running the specs/tests in the [#{MetricFu.rcov[:environment]}] environment"
28
+ mf_debug "** Running the specs/tests in the [#{options[:environment]}] environment"
24
29
  mf_debug "** #{command}"
25
30
  `#{command}`
26
31
  end
@@ -35,17 +40,17 @@ module MetricFu
35
40
  end
36
41
 
37
42
  def default_command
38
- FileUtils.rm_rf(MetricFu::Rcov.metric_directory, :verbose => false)
39
- Dir.mkdir(MetricFu::Rcov.metric_directory)
40
- output = ">> #{MetricFu::Rcov.metric_directory}/rcov.txt"
41
- test_files = FileList[*MetricFu.rcov[:test_files]].join(' ')
42
- rcov_opts = MetricFu.rcov[:rcov_opts].join(' ')
43
- %Q(RAILS_ENV=#{MetricFu.rcov[:environment]} rcov #{test_files} #{rcov_opts} #{output})
43
+ FileUtils.rm_rf(MetricFu::RcovGenerator.metric_directory, :verbose => false)
44
+ Dir.mkdir(MetricFu::RcovGenerator.metric_directory)
45
+ output = ">> #{MetricFu::RcovGenerator.metric_directory}/rcov.txt"
46
+ test_files = FileList[*options[:test_files]].join(' ')
47
+ rcov_opts = options[:rcov_opts].join(' ')
48
+ %Q(RAILS_ENV=#{options[:environment]} rcov #{test_files} #{rcov_opts} #{output})
44
49
  end
45
50
 
46
51
 
47
52
  def analyze
48
- output_file = MetricFu.rcov[:external] ? MetricFu.rcov[:external] : MetricFu::Rcov.metric_directory + '/rcov.txt'
53
+ output_file = options[:external] ? options[:external] : MetricFu::RcovGenerator.metric_directory + '/rcov.txt'
49
54
  output = File.open(output_file).read
50
55
  output = output.split(NEW_FILE_MARKER)
51
56
 
@@ -132,7 +137,7 @@ module MetricFu
132
137
  end
133
138
 
134
139
  def run_rcov?
135
- !(MetricFu.rcov[:external])
140
+ !(options[:external])
136
141
  end
137
142
 
138
143
  end
@@ -1,7 +1,26 @@
1
- MetricFu::Configuration.run do |config|
2
- config.add_metric(:reek)
3
- config.add_graph(:reek)
4
- config.configure_metric(:reek,
5
- { :dirs_to_reek => MetricFu.code_dirs,
6
- :config_file_pattern => nil})
1
+ module MetricFu
2
+ class MetricReek < Metric
3
+
4
+ def name
5
+ :reek
6
+ end
7
+
8
+ def default_run_options
9
+ { :dirs_to_reek => MetricFu::Io::FileSystem.directory('code_dirs'),
10
+ :config_file_pattern => nil}
11
+ end
12
+
13
+ def has_graph?
14
+ true
15
+ end
16
+
17
+ def enable
18
+ super
19
+ end
20
+
21
+ def activate
22
+ super
23
+ end
24
+
25
+ end
7
26
  end
@@ -1,42 +1,25 @@
1
1
  module MetricFu
2
2
 
3
- class Reek < Generator
3
+ class ReekGenerator < Generator
4
4
  REEK_REGEX = /^(\S+) (.*) \((.*)\)$/
5
5
 
6
- def emit
7
- files_to_reek = MetricFu.reek[:dirs_to_reek].map{|dir| Dir[File.join(dir, "**/*.rb")] }
8
- files = remove_excluded_files(files_to_reek.flatten)
9
- config_file_param = MetricFu.reek[:config_file_pattern] ? "--config #{MetricFu.reek[:config_file_pattern]}" : ''
10
- command = %Q(mf-reek #{config_file_param} #{files.join(" ")})
11
- mf_debug "** #{command}"
12
- @output = `#{command}`
13
- @output = massage_for_reek_12 if reek_12?
6
+ def self.metric
7
+ :reek
14
8
  end
15
9
 
16
- def reek_12?
17
- return false if @output.length == 0
18
- (@output =~ /^"/) != 0
10
+ def emit
11
+ files = files_to_analyze
12
+ if files.empty?
13
+ mf_log "Skipping Reek, no files found to analyze"
14
+ @output = ""
15
+ else
16
+ command = %Q(mf-reek #{cli_options(files)})
17
+ mf_debug "** #{command}"
18
+ @output = `#{command}`
19
+ @output = massage_for_reek_12 if reek_12?
20
+ end
19
21
  end
20
22
 
21
- def massage_for_reek_12
22
- section_break = ''
23
- @output.split("\n").map do |line|
24
- case line
25
- when /^ /
26
- "#{line.gsub(/^ /, '')}\n"
27
- else
28
- parts = line.split(" -- ")
29
- if parts[1].nil?
30
- "#{line}\n"
31
- else
32
- warnings = parts[1].gsub(/ \(.*\):/, ':')
33
- result = "#{section_break}\"#{parts[0]}\" -- #{warnings}\n"
34
- section_break = "\n"
35
- result
36
- end
37
- end
38
- end.join
39
- end
40
23
 
41
24
  def analyze
42
25
  @matches = @output.chomp.split("\n\n").map{|m| m.split("\n") }
@@ -80,5 +63,43 @@ module MetricFu
80
63
  end
81
64
  end
82
65
 
66
+ def reek_12?
67
+ return false if @output.length == 0
68
+ (@output =~ /^"/) != 0
69
+ end
70
+
71
+ def massage_for_reek_12
72
+ section_break = ''
73
+ @output.split("\n").map do |line|
74
+ case line
75
+ when /^ /
76
+ "#{line.gsub(/^ /, '')}\n"
77
+ else
78
+ parts = line.split(" -- ")
79
+ if parts[1].nil?
80
+ "#{line}\n"
81
+ else
82
+ warnings = parts[1].gsub(/ \(.*\):/, ':')
83
+ result = "#{section_break}\"#{parts[0]}\" -- #{warnings}\n"
84
+ section_break = "\n"
85
+ result
86
+ end
87
+ end
88
+ end.join
89
+ end
90
+
91
+ private
92
+
93
+ def files_to_analyze
94
+ dirs_to_reek = options[:dirs_to_reek]
95
+ files_to_reek = dirs_to_reek.map{|dir| Dir[File.join(dir, "**","*.rb")] }.flatten
96
+ remove_excluded_files(files_to_reek)
97
+ end
98
+
99
+ def cli_options(files)
100
+ config_file_param = options[:config_file_pattern] ? "--config #{options[:config_file_pattern]}" : ''
101
+ cli_options = "#{config_file_param} #{files.join(' ')}"
102
+ end
103
+
83
104
  end
84
105
  end
@@ -1,6 +1,6 @@
1
1
  <h3>Reek Results</h3>
2
2
 
3
- <p><a href="http://reek.rubyforge.org/">Reek</a> detects common code smells in ruby code.</p>
3
+ <p><a href="http://github.com/troessner/reek">Reek</a> detects common code smells in ruby code.</p>
4
4
 
5
5
  <% graph_name = 'reek' %>
6
6
  <% if MetricFu.configuration.graph_engine == :gchart %>
@@ -1,7 +1,26 @@
1
- MetricFu::Configuration.run do |config|
2
- config.add_metric(:roodi)
3
- config.add_graph(:roodi)
4
- config.configure_metric(:roodi,
5
- { :dirs_to_roodi => MetricFu.code_dirs,
6
- :roodi_config => "#{MetricFu.root_dir}/config/roodi_config.yml"})
1
+ module MetricFu
2
+ class MetricRoodi < Metric
3
+
4
+ def name
5
+ :roodi
6
+ end
7
+
8
+ def default_run_options
9
+ { :dirs_to_roodi => MetricFu::Io::FileSystem.directory('code_dirs'),
10
+ :roodi_config => "#{MetricFu::Io::FileSystem.directory('root_directory')}/config/roodi_config.yml"}
11
+ end
12
+
13
+ def has_graph?
14
+ true
15
+ end
16
+
17
+ def enable
18
+ super
19
+ end
20
+
21
+ def activate
22
+ super
23
+ end
24
+
25
+ end
7
26
  end
@@ -1,10 +1,14 @@
1
1
  module MetricFu
2
- class Roodi < Generator
2
+ class RoodiGenerator < Generator
3
+
4
+ def self.metric
5
+ :roodi
6
+ end
3
7
 
4
8
  def emit
5
- files_to_analyze = MetricFu.roodi[:dirs_to_roodi].map{|dir| Dir[File.join(dir, "**/*.rb")] }
9
+ files_to_analyze = options[:dirs_to_roodi].map{|dir| Dir[File.join(dir, "**/*.rb")] }
6
10
  files = remove_excluded_files(files_to_analyze.flatten)
7
- config = MetricFu.roodi[:roodi_config] ? "-config=#{MetricFu.roodi[:roodi_config]}" : ""
11
+ config = options[:roodi_config] ? "-config=#{options[:roodi_config]}" : ""
8
12
  command = %Q(mf-roodi #{config} #{files.join(" ")})
9
13
  mf_debug "** #{command}"
10
14
  @output = `#{command}`
@@ -1,11 +1,27 @@
1
- MetricFu::Configuration.run do |config|
2
- config.add_metric(:saikuro)
3
- config.configure_metric(:saikuro,
4
- { :output_directory => "#{MetricFu.scratch_directory}/saikuro",
5
- :input_directory =>MetricFu.code_dirs,
1
+ module MetricFu
2
+ class MetricSaikuro < Metric
3
+
4
+ def name
5
+ :saikuro
6
+ end
7
+
8
+ def default_run_options
9
+ { :output_directory => "#{MetricFu::Io::FileSystem.directory('scratch_directory')}/saikuro",
10
+ :input_directory =>MetricFu::Io::FileSystem.directory('code_dirs'),
6
11
  :cyclo => "",
7
12
  :filter_cyclo => "0",
8
13
  :warn_cyclo => "5",
9
14
  :error_cyclo => "7",
10
- :formater => "text"})
15
+ :formater => "text"}
16
+ end
17
+
18
+ def has_graph?
19
+ false
20
+ end
21
+
22
+ def enable
23
+ super
24
+ end
25
+
26
+ end
11
27
  end