bf4-metric_fu 2.1.3.1

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 (127) hide show
  1. data/HISTORY +252 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README.md +49 -0
  4. data/Rakefile +22 -0
  5. data/TODO +6 -0
  6. data/lib/base/base_template.rb +182 -0
  7. data/lib/base/churn_analyzer.rb +38 -0
  8. data/lib/base/code_issue.rb +100 -0
  9. data/lib/base/configuration.rb +219 -0
  10. data/lib/base/flay_analyzer.rb +50 -0
  11. data/lib/base/flog_analyzer.rb +43 -0
  12. data/lib/base/generator.rb +166 -0
  13. data/lib/base/graph.rb +44 -0
  14. data/lib/base/grouping.rb +42 -0
  15. data/lib/base/line_numbers.rb +79 -0
  16. data/lib/base/location.rb +87 -0
  17. data/lib/base/md5_tracker.rb +52 -0
  18. data/lib/base/metric_analyzer.rb +331 -0
  19. data/lib/base/ranking.rb +34 -0
  20. data/lib/base/rcov_analyzer.rb +43 -0
  21. data/lib/base/record.rb +43 -0
  22. data/lib/base/reek_analyzer.rb +164 -0
  23. data/lib/base/report.rb +110 -0
  24. data/lib/base/roodi_analyzer.rb +37 -0
  25. data/lib/base/saikuro_analyzer.rb +48 -0
  26. data/lib/base/scoring_strategies.rb +29 -0
  27. data/lib/base/stats_analyzer.rb +37 -0
  28. data/lib/base/table.rb +108 -0
  29. data/lib/generators/churn.rb +28 -0
  30. data/lib/generators/flay.rb +31 -0
  31. data/lib/generators/flog.rb +113 -0
  32. data/lib/generators/hotspots.rb +52 -0
  33. data/lib/generators/rails_best_practices.rb +53 -0
  34. data/lib/generators/rcov.rb +124 -0
  35. data/lib/generators/reek.rb +81 -0
  36. data/lib/generators/roodi.rb +35 -0
  37. data/lib/generators/saikuro.rb +259 -0
  38. data/lib/generators/stats.rb +58 -0
  39. data/lib/graphs/engines/bluff.rb +113 -0
  40. data/lib/graphs/engines/gchart.rb +157 -0
  41. data/lib/graphs/flay_grapher.rb +18 -0
  42. data/lib/graphs/flog_grapher.rb +57 -0
  43. data/lib/graphs/grapher.rb +11 -0
  44. data/lib/graphs/rails_best_practices_grapher.rb +19 -0
  45. data/lib/graphs/rcov_grapher.rb +18 -0
  46. data/lib/graphs/reek_grapher.rb +30 -0
  47. data/lib/graphs/roodi_grapher.rb +18 -0
  48. data/lib/graphs/stats_grapher.rb +20 -0
  49. data/lib/metric_fu.rb +80 -0
  50. data/lib/tasks/metric_fu.rake +36 -0
  51. data/lib/templates/awesome/awesome_template.rb +92 -0
  52. data/lib/templates/awesome/churn.html.erb +58 -0
  53. data/lib/templates/awesome/css/buttons.css +82 -0
  54. data/lib/templates/awesome/css/default.css +91 -0
  55. data/lib/templates/awesome/css/integrity.css +334 -0
  56. data/lib/templates/awesome/css/reset.css +7 -0
  57. data/lib/templates/awesome/css/syntax.css +19 -0
  58. data/lib/templates/awesome/flay.html.erb +34 -0
  59. data/lib/templates/awesome/flog.html.erb +55 -0
  60. data/lib/templates/awesome/hotspots.html.erb +62 -0
  61. data/lib/templates/awesome/index.html.erb +34 -0
  62. data/lib/templates/awesome/layout.html.erb +30 -0
  63. data/lib/templates/awesome/rails_best_practices.html.erb +27 -0
  64. data/lib/templates/awesome/rcov.html.erb +42 -0
  65. data/lib/templates/awesome/reek.html.erb +40 -0
  66. data/lib/templates/awesome/roodi.html.erb +27 -0
  67. data/lib/templates/awesome/saikuro.html.erb +71 -0
  68. data/lib/templates/awesome/stats.html.erb +51 -0
  69. data/lib/templates/javascripts/bluff-min.js +1 -0
  70. data/lib/templates/javascripts/excanvas.js +35 -0
  71. data/lib/templates/javascripts/js-class.js +1 -0
  72. data/lib/templates/standard/churn.html.erb +31 -0
  73. data/lib/templates/standard/default.css +64 -0
  74. data/lib/templates/standard/flay.html.erb +34 -0
  75. data/lib/templates/standard/flog.html.erb +57 -0
  76. data/lib/templates/standard/hotspots.html.erb +54 -0
  77. data/lib/templates/standard/index.html.erb +41 -0
  78. data/lib/templates/standard/rails_best_practices.html.erb +29 -0
  79. data/lib/templates/standard/rcov.html.erb +43 -0
  80. data/lib/templates/standard/reek.html.erb +42 -0
  81. data/lib/templates/standard/roodi.html.erb +29 -0
  82. data/lib/templates/standard/saikuro.html.erb +84 -0
  83. data/lib/templates/standard/standard_template.rb +27 -0
  84. data/lib/templates/standard/stats.html.erb +55 -0
  85. data/spec/base/base_template_spec.rb +194 -0
  86. data/spec/base/configuration_spec.rb +277 -0
  87. data/spec/base/generator_spec.rb +223 -0
  88. data/spec/base/graph_spec.rb +61 -0
  89. data/spec/base/line_numbers_spec.rb +62 -0
  90. data/spec/base/location_spec.rb +127 -0
  91. data/spec/base/md5_tracker_spec.rb +57 -0
  92. data/spec/base/metric_analyzer_spec.rb +452 -0
  93. data/spec/base/ranking_spec.rb +42 -0
  94. data/spec/base/report_spec.rb +146 -0
  95. data/spec/base/table_spec.rb +36 -0
  96. data/spec/generators/churn_spec.rb +41 -0
  97. data/spec/generators/flay_spec.rb +105 -0
  98. data/spec/generators/flog_spec.rb +70 -0
  99. data/spec/generators/hotspots_spec.rb +88 -0
  100. data/spec/generators/rails_best_practices_spec.rb +52 -0
  101. data/spec/generators/rcov_spec.rb +180 -0
  102. data/spec/generators/reek_spec.rb +134 -0
  103. data/spec/generators/roodi_spec.rb +24 -0
  104. data/spec/generators/saikuro_spec.rb +74 -0
  105. data/spec/generators/stats_spec.rb +74 -0
  106. data/spec/graphs/engines/bluff_spec.rb +19 -0
  107. data/spec/graphs/engines/gchart_spec.rb +156 -0
  108. data/spec/graphs/flay_grapher_spec.rb +56 -0
  109. data/spec/graphs/flog_grapher_spec.rb +108 -0
  110. data/spec/graphs/rails_best_practices_grapher_spec.rb +61 -0
  111. data/spec/graphs/rcov_grapher_spec.rb +56 -0
  112. data/spec/graphs/reek_grapher_spec.rb +65 -0
  113. data/spec/graphs/roodi_grapher_spec.rb +56 -0
  114. data/spec/graphs/stats_grapher_spec.rb +68 -0
  115. data/spec/resources/line_numbers/foo.rb +33 -0
  116. data/spec/resources/line_numbers/module.rb +11 -0
  117. data/spec/resources/line_numbers/module_surrounds_class.rb +15 -0
  118. data/spec/resources/line_numbers/two_classes.rb +11 -0
  119. data/spec/resources/saikuro/app/controllers/sessions_controller.rb_cyclo.html +10 -0
  120. data/spec/resources/saikuro/app/controllers/users_controller.rb_cyclo.html +16 -0
  121. data/spec/resources/saikuro/index_cyclo.html +155 -0
  122. data/spec/resources/saikuro_sfiles/thing.rb_cyclo.html +11 -0
  123. data/spec/resources/yml/20090630.yml +7922 -0
  124. data/spec/resources/yml/metric_missing.yml +1 -0
  125. data/spec/spec.opts +6 -0
  126. data/spec/spec_helper.rb +7 -0
  127. metadata +560 -0
@@ -0,0 +1,28 @@
1
+ module MetricFu
2
+
3
+ class Churn < Generator
4
+
5
+ def initialize(options={})
6
+ super
7
+ end
8
+
9
+ def emit
10
+ @output = `churn --yaml`
11
+ yaml_start = @output.index("---")
12
+ @output = @output[yaml_start...@output.length] if yaml_start
13
+ end
14
+
15
+ def analyze
16
+ if @output.match(/Churning requires a subversion or git repo/)
17
+ @churn = [:churn => {}]
18
+ else
19
+ @churn = YAML::load(@output)
20
+ end
21
+ end
22
+
23
+ def to_h
24
+ {:churn => @churn[:churn]}
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,31 @@
1
+ require 'flay'
2
+
3
+ module MetricFu
4
+
5
+ class Flay < Generator
6
+
7
+ def emit
8
+ mimimum_score_parameter = MetricFu.flay[:minimum_score] ? "--mass #{MetricFu.flay[:minimum_score]} " : ""
9
+
10
+ @output = `flay #{mimimum_score_parameter} #{MetricFu.flay[:dirs_to_flay].join(" ")}`
11
+ end
12
+
13
+ def analyze
14
+ @matches = @output.chomp.split("\n\n").map{|m| m.split("\n ") }
15
+ end
16
+
17
+ def to_h
18
+ target = []
19
+ total_score = @matches.shift.first.split('=').last.strip
20
+ @matches.each do |problem|
21
+ reason = problem.shift.strip
22
+ lines_info = problem.map do |full_line|
23
+ name, line = full_line.split(":")
24
+ {:name => name.strip, :line => line.strip}
25
+ end
26
+ target << [:reason => reason, :matches => lines_info]
27
+ end
28
+ {:flay => {:total_score => total_score, :matches => target.flatten}}
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,113 @@
1
+ require 'pathname'
2
+ require 'optparse'
3
+ require 'flog'
4
+
5
+ module MetricFu
6
+
7
+ class Flog < Generator
8
+
9
+ def emit
10
+ files = []
11
+ MetricFu.flog[:dirs_to_flog].each do |directory|
12
+ directory = "." if directory=='./'
13
+ dir_files = Dir.glob("#{directory}/**/*.rb")
14
+ dir_files = remove_excluded_files(dir_files)
15
+ files += dir_files
16
+ end
17
+ options = ::Flog.parse_options ["--all", "--details"]
18
+ # TODO determine if flogging should continue despite errors
19
+ # options = ::Flog.parse_options ["--all", "--details", "--continue"]
20
+
21
+ @flogger = ::Flog.new options
22
+ @flogger.flog files
23
+
24
+ rescue LoadError
25
+ if RUBY_PLATFORM =~ /java/
26
+ puts 'running in jruby - flog tasks not available'
27
+ end
28
+ end
29
+
30
+ def analyze
31
+ @method_containers = {}
32
+ @flogger.calls.each do |full_method_name, operators|
33
+ container_name = full_method_name.split('#').first
34
+ path = @flogger.method_locations[full_method_name]
35
+ if @method_containers[container_name]
36
+ @method_containers[container_name].add_method(full_method_name, operators, @flogger.totals[full_method_name], path)
37
+ @method_containers[container_name].add_path(path)
38
+ else
39
+ mc = MethodContainer.new(container_name, path)
40
+ mc.add_method(full_method_name, operators, @flogger.totals[full_method_name], path)
41
+ @method_containers[container_name] = mc
42
+ end
43
+ end
44
+ end
45
+
46
+ def to_h
47
+ sorted_containers = @method_containers.values.sort_by {|c| c.highest_score}.reverse
48
+ {:flog => { :total => @flogger.total,
49
+ :average => @flogger.average,
50
+ :method_containers => sorted_containers.map {|method_container| method_container.to_h}}}
51
+ end
52
+
53
+ def per_file_info(out)
54
+ @method_containers.each_pair do |klass, container|
55
+ container.methods.each_pair do |method_name, data|
56
+ next if data[:path].nil?
57
+
58
+ file, line = data[:path].split(':')
59
+
60
+ out[file] ||= {}
61
+ out[file][line] ||= []
62
+ out[file][line] << {:type => :flog, :description => "Score of %.2f" % data[:score]}
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ class MethodContainer
69
+ attr_reader :methods
70
+
71
+ def initialize(name, path)
72
+ @name = name
73
+ add_path path
74
+ @methods = {}
75
+ end
76
+
77
+ def add_path path
78
+ return unless path
79
+ @path ||= path.split(':').first
80
+ end
81
+
82
+ def add_method(full_method_name, operators, score, path)
83
+ @methods[full_method_name] = {:operators => operators, :score => score, :path => path}
84
+ end
85
+
86
+ def to_h
87
+ { :name => @name,
88
+ :path => @path || '',
89
+ :total_score => total_score,
90
+ :highest_score => highest_score,
91
+ :average_score => average_score,
92
+ :methods => @methods}
93
+ end
94
+
95
+ def highest_score
96
+ method_scores.max
97
+ end
98
+
99
+ private
100
+
101
+ def method_scores
102
+ @method_scores ||= @methods.values.map {|v| v[:score] }
103
+ end
104
+
105
+ def total_score
106
+ @total_score ||= method_scores.inject(0) {|sum, score| sum += score}
107
+ end
108
+
109
+ def average_score
110
+ total_score / method_scores.size.to_f
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,52 @@
1
+ module MetricFu
2
+
3
+ class Hotspots < Generator
4
+
5
+ def initialize(options={})
6
+ super
7
+ end
8
+
9
+ def self.verify_dependencies!
10
+ true
11
+ end
12
+
13
+ def emit
14
+ @analyzer = MetricAnalyzer.new(MetricFu.report.report_hash)
15
+ end
16
+
17
+ def analyze
18
+ num = nil
19
+ worst_items = {}
20
+ if @analyzer
21
+ worst_items[:files] =
22
+ @analyzer.worst_files(num).inject([]) do |array, worst_file|
23
+ array <<
24
+ {:location => @analyzer.location(:file, worst_file),
25
+ :details => @analyzer.problems_with(:file, worst_file)}
26
+ array
27
+ end
28
+ worst_items[:classes] = @analyzer.worst_classes(num).inject([]) do |array, class_name|
29
+ location = @analyzer.location(:class, class_name)
30
+ array <<
31
+ {:location => location,
32
+ :details => @analyzer.problems_with(:class, class_name)}
33
+ array
34
+ end
35
+ worst_items[:methods] = @analyzer.worst_methods(num).inject([]) do |array, method_name|
36
+ location = @analyzer.location(:method, method_name)
37
+ array <<
38
+ {:location => location,
39
+ :details => @analyzer.problems_with(:method, method_name)}
40
+ array
41
+ end
42
+ end
43
+
44
+ @hotspots = worst_items
45
+ end
46
+
47
+ def to_h
48
+ {:hotspots => @hotspots}
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,53 @@
1
+ module MetricFu
2
+ class RailsBestPractices < Generator
3
+
4
+ def emit
5
+ @output = `rails_best_practices --without-color .`
6
+ end
7
+
8
+ def analyze
9
+ @matches = @output.chomp.split("\n").map{|m| m.split(" - ") }
10
+ total = @matches.pop
11
+ cleanup_color_switches(total.first)
12
+
13
+ 2.times { @matches.pop } # ignore wiki link
14
+ @matches.reject! {|array| array.empty? }
15
+ @matches.map! do |match|
16
+ file, line = match[0].split(':')
17
+ problem = match[1]
18
+
19
+ cleanup_color_switches(file)
20
+ cleanup_color_switches(problem)
21
+
22
+ file.gsub!(/^\.\//, '')
23
+
24
+ {:file => file, :line => line, :problem => problem}
25
+ end
26
+ @rails_best_practices_results = {:total => total, :problems => @matches}
27
+ end
28
+
29
+ def cleanup_color_switches(str)
30
+ return if str.nil?
31
+ str.gsub!(%r{^\e\[3[1|2]m}, '')
32
+ str.gsub!(%r{\e\[0m$}, '')
33
+ end
34
+
35
+ def to_h
36
+ {:rails_best_practices => @rails_best_practices_results}
37
+ end
38
+
39
+ def per_file_info(out)
40
+ @rails_best_practices_results[:problems].each do |problem|
41
+ next if problem[:file] == '' || problem[:problem].nil?
42
+
43
+ out[problem[:file]] ||= {}
44
+
45
+ lines = problem[:line].split(/\s*,\s*/)
46
+ lines.each do |line|
47
+ out[problem[:file]][line] ||= []
48
+ out[problem[:file]][line] << {:type => :rails_best_practices, :description => problem[:problem]}
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,124 @@
1
+ require 'enumerator'
2
+
3
+ module MetricFu
4
+
5
+ class Rcov < Generator
6
+ NEW_FILE_MARKER = /^={80}$/.freeze
7
+
8
+ class Line
9
+ attr_accessor :content, :was_run
10
+
11
+ def initialize(content, was_run)
12
+ @content = content
13
+ @was_run = was_run
14
+ end
15
+
16
+ def to_h
17
+ {:content => @content, :was_run => @was_run}
18
+ end
19
+ end
20
+
21
+ def emit
22
+ unless MetricFu.rcov[:external]
23
+ FileUtils.rm_rf(MetricFu::Rcov.metric_directory, :verbose => false)
24
+ Dir.mkdir(MetricFu::Rcov.metric_directory)
25
+ test_files = FileList[*MetricFu.rcov[:test_files]].join(' ')
26
+ rcov_opts = MetricFu.rcov[:rcov_opts].join(' ')
27
+ output = ">> #{MetricFu::Rcov.metric_directory}/rcov.txt"
28
+ mf_debug "** Running the specs/tests in the [#{MetricFu.rcov[:environment]}] environment"
29
+ command = %Q(RAILS_ENV=#{MetricFu.rcov[:environment]} rcov #{test_files} #{rcov_opts} #{output})
30
+ mf_debug "** #{command}"
31
+ `#{command}`
32
+ end
33
+ end
34
+
35
+
36
+ def analyze
37
+ output_file = MetricFu.rcov[:external] ? MetricFu.rcov[:external] : MetricFu::Rcov.metric_directory + '/rcov.txt'
38
+ output = File.open(output_file).read
39
+ output = output.split(NEW_FILE_MARKER)
40
+
41
+ output.shift # Throw away the first entry - it's the execution time etc.
42
+
43
+ files = assemble_files(output)
44
+
45
+ @global_total_lines = 0
46
+ @global_total_lines_run = 0
47
+
48
+ @rcov = add_coverage_percentage(files)
49
+ end
50
+
51
+ def to_h
52
+ global_percent_run = ((@global_total_lines_run.to_f / @global_total_lines.to_f) * 100)
53
+ add_method_data
54
+ {:rcov => @rcov.merge({:global_percent_run => round_to_tenths(global_percent_run) })}
55
+ end
56
+
57
+ private
58
+
59
+ def add_method_data
60
+ @rcov.each_pair do |file_path, info|
61
+ file_contents = ""
62
+ coverage = []
63
+
64
+ info[:lines].each_with_index do |line, index|
65
+ file_contents << "#{line[:content]}\n"
66
+ coverage << line[:was_run]
67
+ end
68
+
69
+ begin
70
+ line_numbers = MetricFu::LineNumbers.new(file_contents)
71
+ rescue StandardError => e
72
+ raise e unless e.message =~ /you shouldn't be able to get here/
73
+ STDOUT.puts "ruby_parser blew up while trying to parse #{file_path}. You won't have method level Rcov information for this file."
74
+ next
75
+ end
76
+
77
+ method_coverage_map = {}
78
+ coverage.each_with_index do |covered, index|
79
+ line_number = index + 1
80
+ if line_numbers.in_method?(line_number)
81
+ method_name = line_numbers.method_at_line(line_number)
82
+ method_coverage_map[method_name] ||= {}
83
+ method_coverage_map[method_name][:total] ||= 0
84
+ method_coverage_map[method_name][:total] += 1
85
+ method_coverage_map[method_name][:uncovered] ||= 0
86
+ method_coverage_map[method_name][:uncovered] += 1 if !covered
87
+ end
88
+ end
89
+
90
+ @rcov[file_path][:methods] = {}
91
+
92
+ method_coverage_map.each do |method_name, coverage_data|
93
+ @rcov[file_path][:methods][method_name] = (coverage_data[:uncovered] / coverage_data[:total].to_f) * 100.0
94
+ end
95
+
96
+ end
97
+ end
98
+
99
+ def assemble_files(output)
100
+ files = {}
101
+ output.each_slice(2) {|out| files[out.first.strip] = out.last}
102
+ files.each_pair {|fname, content| files[fname] = content.split("\n") }
103
+ files.each_pair do |fname, content|
104
+ content.map! do |raw_line|
105
+ line = Line.new(raw_line[3..-1], !raw_line.match(/^!!/)).to_h
106
+ end
107
+ content.reject! {|line| line[:content].blank? }
108
+ files[fname] = {:lines => content}
109
+ end
110
+ files
111
+ end
112
+
113
+ def add_coverage_percentage(files)
114
+ files.each_pair do |fname, content|
115
+ lines = content[:lines]
116
+ @global_total_lines_run += lines_run = lines.find_all {|line| line[:was_run] == true }.length
117
+ @global_total_lines += total_lines = lines.length
118
+ percent_run = ((lines_run.to_f / total_lines.to_f) * 100).round
119
+ files[fname][:percent_run] = percent_run
120
+ end
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,81 @@
1
+ module MetricFu
2
+
3
+ class Reek < Generator
4
+ REEK_REGEX = /^(\S+) (.*) \((.*)\)$/
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
+ @output = `reek #{config_file_param} #{files.join(" ")}`
11
+ @output = massage_for_reek_12 if reek_12?
12
+ end
13
+
14
+ def reek_12?
15
+ return false if @output.length == 0
16
+ (@output =~ /^"/) != 0
17
+ end
18
+
19
+ def massage_for_reek_12
20
+ section_break = ''
21
+ @output.split("\n").map do |line|
22
+ case line
23
+ when /^ /
24
+ "#{line.gsub(/^ /, '')}\n"
25
+ else
26
+ parts = line.split(" -- ")
27
+ if parts[1].nil?
28
+ "#{line}\n"
29
+ else
30
+ warnings = parts[1].gsub(/ \(.*\):/, ':')
31
+ result = "#{section_break}\"#{parts[0]}\" -- #{warnings}\n"
32
+ section_break = "\n"
33
+ result
34
+ end
35
+ end
36
+ end.join
37
+ end
38
+
39
+ def analyze
40
+ @matches = @output.chomp.split("\n\n").map{|m| m.split("\n") }
41
+ @matches = @matches.map do |match|
42
+ file_path = match.shift.split('--').first
43
+ file_path = file_path.gsub('"', ' ').strip
44
+ code_smells = match.map do |smell|
45
+ match_object = smell.match(REEK_REGEX)
46
+ next unless match_object
47
+ {:method => match_object[1].strip,
48
+ :message => match_object[2].strip,
49
+ :type => match_object[3].strip}
50
+ end.compact
51
+ {:file_path => file_path, :code_smells => code_smells}
52
+ end
53
+ end
54
+
55
+ def to_h
56
+ {:reek => {:matches => @matches}}
57
+ end
58
+
59
+ def per_file_info(out)
60
+ @matches.each do |file_data|
61
+ next if File.extname(file_data[:file_path]) == '.erb'
62
+ begin
63
+ line_numbers = MetricFu::LineNumbers.new(File.open(file_data[:file_path], 'r').read)
64
+ rescue StandardError => e
65
+ raise e unless e.message =~ /you shouldn't be able to get here/
66
+ puts "ruby_parser blew up while trying to parse #{file_path}. You won't have method level reek information for this file."
67
+ next
68
+ end
69
+
70
+ out[file_data[:file_path]] ||= {}
71
+ file_data[:code_smells].each do |smell_data|
72
+ line = line_numbers.start_line_for_method(smell_data[:method])
73
+ out[file_data[:file_path]][line.to_s] ||= []
74
+ out[file_data[:file_path]][line.to_s] << {:type => :reek,
75
+ :description => "#{smell_data[:type]} - #{smell_data[:message]}"}
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+ end