fastruby-metric_fu 5.0.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 (296) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.metrics +3 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +15 -0
  6. data/.rubocop_todo.yml +69 -0
  7. data/.simplecov +74 -0
  8. data/.travis.yml +18 -0
  9. data/.yardopts +4 -0
  10. data/AUTHORS +12 -0
  11. data/CONTRIBUTING.md +47 -0
  12. data/CONTRIBUTORS +76 -0
  13. data/DEV.md +76 -0
  14. data/Gemfile +58 -0
  15. data/Guardfile +30 -0
  16. data/HISTORY.md +705 -0
  17. data/MIT-LICENSE +22 -0
  18. data/README.md +299 -0
  19. data/Rakefile +27 -0
  20. data/TODO.md +118 -0
  21. data/appveyor.yml +29 -0
  22. data/bin/metric_fu +9 -0
  23. data/bin/mf-cane +10 -0
  24. data/bin/mf-churn +10 -0
  25. data/bin/mf-flay +10 -0
  26. data/bin/mf-reek +10 -0
  27. data/bin/mf-roodi +10 -0
  28. data/bin/mf-saikuro +10 -0
  29. data/certs/bf4.pem +22 -0
  30. data/checksum/.gitkeep +0 -0
  31. data/checksum/metric_fu-4.10.0.gem.sha512 +1 -0
  32. data/checksum/metric_fu-4.11.0.gem.sha512 +1 -0
  33. data/checksum/metric_fu-4.11.1.gem.sha512 +1 -0
  34. data/checksum/metric_fu-4.11.2.gem.sha512 +1 -0
  35. data/checksum/metric_fu-4.11.3.gem.sha512 +1 -0
  36. data/checksum/metric_fu-4.11.4.gem.sha512 +1 -0
  37. data/checksum/metric_fu-4.12.0.gem.sha512 +1 -0
  38. data/checksum/metric_fu-4.2.0.gem.sha512 +1 -0
  39. data/checksum/metric_fu-4.2.1.gem.sha512 +1 -0
  40. data/checksum/metric_fu-4.3.0.gem.sha512 +1 -0
  41. data/checksum/metric_fu-4.3.1.gem.sha512 +1 -0
  42. data/checksum/metric_fu-4.4.0.gem.sha512 +1 -0
  43. data/checksum/metric_fu-4.4.1.gem.sha512 +1 -0
  44. data/checksum/metric_fu-4.4.2.gem.sha512 +1 -0
  45. data/checksum/metric_fu-4.4.3.gem.sha512 +1 -0
  46. data/checksum/metric_fu-4.4.4.gem.sha512 +1 -0
  47. data/checksum/metric_fu-4.5.0.gem.sha512 +1 -0
  48. data/checksum/metric_fu-4.5.1.gem.sha512 +1 -0
  49. data/checksum/metric_fu-4.5.2.gem.sha512 +1 -0
  50. data/checksum/metric_fu-4.6.0.gem.sha512 +1 -0
  51. data/checksum/metric_fu-4.7.0.gem.sha512 +1 -0
  52. data/checksum/metric_fu-4.7.1.gem.sha512 +1 -0
  53. data/checksum/metric_fu-4.7.2.gem.sha512 +1 -0
  54. data/checksum/metric_fu-4.7.3.gem.sha512 +1 -0
  55. data/checksum/metric_fu-4.7.4.gem.sha512 +1 -0
  56. data/checksum/metric_fu-4.8.0.gem.sha512 +1 -0
  57. data/checksum/metric_fu-4.9.0.gem.sha512 +1 -0
  58. data/config/roodi_config.yml +22 -0
  59. data/config/rubocop.yml +269 -0
  60. data/gem_tasks/build.rake +197 -0
  61. data/gem_tasks/rubocop.rake +10 -0
  62. data/gem_tasks/usage_test.rake +19 -0
  63. data/gem_tasks/yard.rake +24 -0
  64. data/lib/metric_fu.rb +151 -0
  65. data/lib/metric_fu/calculate.rb +10 -0
  66. data/lib/metric_fu/cli/client.rb +26 -0
  67. data/lib/metric_fu/cli/helper.rb +80 -0
  68. data/lib/metric_fu/cli/parser.rb +138 -0
  69. data/lib/metric_fu/configuration.rb +150 -0
  70. data/lib/metric_fu/constantize.rb +57 -0
  71. data/lib/metric_fu/data_structures/line_numbers.rb +112 -0
  72. data/lib/metric_fu/data_structures/location.rb +110 -0
  73. data/lib/metric_fu/data_structures/sexp_node.rb +107 -0
  74. data/lib/metric_fu/environment.rb +129 -0
  75. data/lib/metric_fu/errors/analysis_error.rb +4 -0
  76. data/lib/metric_fu/formatter.rb +40 -0
  77. data/lib/metric_fu/formatter/html.rb +96 -0
  78. data/lib/metric_fu/formatter/syntax.rb +45 -0
  79. data/lib/metric_fu/formatter/yaml.rb +18 -0
  80. data/lib/metric_fu/gem_run.rb +70 -0
  81. data/lib/metric_fu/gem_version.rb +92 -0
  82. data/lib/metric_fu/generator.rb +135 -0
  83. data/lib/metric_fu/io.rb +132 -0
  84. data/lib/metric_fu/loader.rb +105 -0
  85. data/lib/metric_fu/logger.rb +62 -0
  86. data/lib/metric_fu/logging/mf_debugger.rb +23 -0
  87. data/lib/metric_fu/metric.rb +143 -0
  88. data/lib/metric_fu/metrics/cane/generator.rb +95 -0
  89. data/lib/metric_fu/metrics/cane/grapher.rb +37 -0
  90. data/lib/metric_fu/metrics/cane/metric.rb +34 -0
  91. data/lib/metric_fu/metrics/cane/report.html.erb +87 -0
  92. data/lib/metric_fu/metrics/cane/violations.rb +46 -0
  93. data/lib/metric_fu/metrics/churn/generator.rb +37 -0
  94. data/lib/metric_fu/metrics/churn/hotspot.rb +43 -0
  95. data/lib/metric_fu/metrics/churn/metric.rb +29 -0
  96. data/lib/metric_fu/metrics/churn/report.html.erb +58 -0
  97. data/lib/metric_fu/metrics/flay/generator.rb +51 -0
  98. data/lib/metric_fu/metrics/flay/grapher.rb +37 -0
  99. data/lib/metric_fu/metrics/flay/hotspot.rb +52 -0
  100. data/lib/metric_fu/metrics/flay/metric.rb +28 -0
  101. data/lib/metric_fu/metrics/flay/report.html.erb +29 -0
  102. data/lib/metric_fu/metrics/flog/generator.rb +113 -0
  103. data/lib/metric_fu/metrics/flog/grapher.rb +77 -0
  104. data/lib/metric_fu/metrics/flog/hotspot.rb +46 -0
  105. data/lib/metric_fu/metrics/flog/metric.rb +29 -0
  106. data/lib/metric_fu/metrics/flog/report.html.erb +50 -0
  107. data/lib/metric_fu/metrics/hotspots/analysis/analyzed_problems.rb +34 -0
  108. data/lib/metric_fu/metrics/hotspots/analysis/analyzer_tables.rb +114 -0
  109. data/lib/metric_fu/metrics/hotspots/analysis/grouping.rb +23 -0
  110. data/lib/metric_fu/metrics/hotspots/analysis/groupings.rb +12 -0
  111. data/lib/metric_fu/metrics/hotspots/analysis/problems.rb +20 -0
  112. data/lib/metric_fu/metrics/hotspots/analysis/ranked_problem_location.rb +70 -0
  113. data/lib/metric_fu/metrics/hotspots/analysis/ranking.rb +29 -0
  114. data/lib/metric_fu/metrics/hotspots/analysis/rankings.rb +91 -0
  115. data/lib/metric_fu/metrics/hotspots/analysis/record.rb +32 -0
  116. data/lib/metric_fu/metrics/hotspots/analysis/scoring_strategies.rb +24 -0
  117. data/lib/metric_fu/metrics/hotspots/analysis/table.rb +67 -0
  118. data/lib/metric_fu/metrics/hotspots/generator.rb +40 -0
  119. data/lib/metric_fu/metrics/hotspots/hotspot.rb +87 -0
  120. data/lib/metric_fu/metrics/hotspots/hotspot_analyzer.rb +61 -0
  121. data/lib/metric_fu/metrics/hotspots/metric.rb +20 -0
  122. data/lib/metric_fu/metrics/hotspots/report.html.erb +60 -0
  123. data/lib/metric_fu/metrics/rails_best_practices/generator.rb +47 -0
  124. data/lib/metric_fu/metrics/rails_best_practices/grapher.rb +38 -0
  125. data/lib/metric_fu/metrics/rails_best_practices/metric.rb +31 -0
  126. data/lib/metric_fu/metrics/rails_best_practices/report.html.erb +22 -0
  127. data/lib/metric_fu/metrics/rcov/external_client.rb +22 -0
  128. data/lib/metric_fu/metrics/rcov/generator.rb +75 -0
  129. data/lib/metric_fu/metrics/rcov/grapher.rb +37 -0
  130. data/lib/metric_fu/metrics/rcov/hotspot.rb +46 -0
  131. data/lib/metric_fu/metrics/rcov/metric.rb +61 -0
  132. data/lib/metric_fu/metrics/rcov/rcov_format_coverage.rb +149 -0
  133. data/lib/metric_fu/metrics/rcov/rcov_line.rb +48 -0
  134. data/lib/metric_fu/metrics/rcov/report.html.erb +40 -0
  135. data/lib/metric_fu/metrics/rcov/simplecov_formatter.rb +74 -0
  136. data/lib/metric_fu/metrics/reek/generator.rb +94 -0
  137. data/lib/metric_fu/metrics/reek/grapher.rb +55 -0
  138. data/lib/metric_fu/metrics/reek/hotspot.rb +95 -0
  139. data/lib/metric_fu/metrics/reek/metric.rb +26 -0
  140. data/lib/metric_fu/metrics/reek/report.html.erb +35 -0
  141. data/lib/metric_fu/metrics/roodi/generator.rb +40 -0
  142. data/lib/metric_fu/metrics/roodi/grapher.rb +37 -0
  143. data/lib/metric_fu/metrics/roodi/hotspot.rb +39 -0
  144. data/lib/metric_fu/metrics/roodi/metric.rb +24 -0
  145. data/lib/metric_fu/metrics/roodi/report.html.erb +22 -0
  146. data/lib/metric_fu/metrics/saikuro/generator.rb +145 -0
  147. data/lib/metric_fu/metrics/saikuro/hotspot.rb +51 -0
  148. data/lib/metric_fu/metrics/saikuro/metric.rb +31 -0
  149. data/lib/metric_fu/metrics/saikuro/parsing_element.rb +37 -0
  150. data/lib/metric_fu/metrics/saikuro/report.html.erb +71 -0
  151. data/lib/metric_fu/metrics/saikuro/scratch_file.rb +108 -0
  152. data/lib/metric_fu/metrics/stats/generator.rb +82 -0
  153. data/lib/metric_fu/metrics/stats/grapher.rb +40 -0
  154. data/lib/metric_fu/metrics/stats/hotspot.rb +35 -0
  155. data/lib/metric_fu/metrics/stats/metric.rb +28 -0
  156. data/lib/metric_fu/metrics/stats/report.html.erb +44 -0
  157. data/lib/metric_fu/reporter.rb +37 -0
  158. data/lib/metric_fu/reporting/graphs/graph.rb +69 -0
  159. data/lib/metric_fu/reporting/graphs/grapher.rb +66 -0
  160. data/lib/metric_fu/reporting/result.rb +59 -0
  161. data/lib/metric_fu/run.rb +82 -0
  162. data/lib/metric_fu/tasks/metric_fu.rake +54 -0
  163. data/lib/metric_fu/templates/_graph.html.erb +2 -0
  164. data/lib/metric_fu/templates/_report_footer.html.erb +1 -0
  165. data/lib/metric_fu/templates/configuration.rb +25 -0
  166. data/lib/metric_fu/templates/css/bluff.css +15 -0
  167. data/lib/metric_fu/templates/css/buttons.css +82 -0
  168. data/lib/metric_fu/templates/css/default.css +43 -0
  169. data/lib/metric_fu/templates/css/integrity.css +337 -0
  170. data/lib/metric_fu/templates/css/rcov.css +32 -0
  171. data/lib/metric_fu/templates/css/reset.css +7 -0
  172. data/lib/metric_fu/templates/css/syntax.css +19 -0
  173. data/lib/metric_fu/templates/index.html.erb +10 -0
  174. data/lib/metric_fu/templates/javascripts/bluff-min.js +1 -0
  175. data/lib/metric_fu/templates/javascripts/bluff_graph.js +15 -0
  176. data/lib/metric_fu/templates/javascripts/excanvas.js +35 -0
  177. data/lib/metric_fu/templates/javascripts/highcharts.js +294 -0
  178. data/lib/metric_fu/templates/javascripts/highcharts_graph.js +38 -0
  179. data/lib/metric_fu/templates/javascripts/js-class.js +1 -0
  180. data/lib/metric_fu/templates/javascripts/standalone-framework.js +17 -0
  181. data/lib/metric_fu/templates/javascripts/utils.js +9 -0
  182. data/lib/metric_fu/templates/layout.html.erb +37 -0
  183. data/lib/metric_fu/templates/metrics_template.rb +80 -0
  184. data/lib/metric_fu/templates/report.html.erb +31 -0
  185. data/lib/metric_fu/templates/report.rb +41 -0
  186. data/lib/metric_fu/templates/template.rb +244 -0
  187. data/lib/metric_fu/utility.rb +79 -0
  188. data/lib/metric_fu/version.rb +9 -0
  189. data/metric_fu.gemspec +71 -0
  190. data/spec/capture_warnings.rb +55 -0
  191. data/spec/cli/helper_spec.rb +165 -0
  192. data/spec/dummy/.gitignore +1 -0
  193. data/spec/dummy/.gitkeep +0 -0
  194. data/spec/dummy/lib/.gitkeep +0 -0
  195. data/spec/dummy/lib/bad_encoding.rb +6 -0
  196. data/spec/dummy/spec/.gitkeep +0 -0
  197. data/spec/fixtures/20090630.yml +7922 -0
  198. data/spec/fixtures/coverage-153.rb +11 -0
  199. data/spec/fixtures/coverage.rb +13 -0
  200. data/spec/fixtures/exit0.sh +3 -0
  201. data/spec/fixtures/exit1.sh +3 -0
  202. data/spec/fixtures/hotspots/flog.yml +86 -0
  203. data/spec/fixtures/hotspots/generator.yml +47 -0
  204. data/spec/fixtures/hotspots/generator_analysis.yml +53 -0
  205. data/spec/fixtures/hotspots/reek.yml +14 -0
  206. data/spec/fixtures/hotspots/roodi.yml +13 -0
  207. data/spec/fixtures/hotspots/saikuro.yml +27 -0
  208. data/spec/fixtures/hotspots/several_metrics.yml +47 -0
  209. data/spec/fixtures/hotspots/stats.yml +4 -0
  210. data/spec/fixtures/hotspots/three_metrics_on_same_file.yml +36 -0
  211. data/spec/fixtures/line_numbers/foo.rb +33 -0
  212. data/spec/fixtures/line_numbers/module.rb +11 -0
  213. data/spec/fixtures/line_numbers/module_surrounds_class.rb +15 -0
  214. data/spec/fixtures/line_numbers/two_classes.rb +11 -0
  215. data/spec/fixtures/metric_missing.yml +1 -0
  216. data/spec/fixtures/rcov_output.txt +135 -0
  217. data/spec/fixtures/saikuro/app/controllers/sessions_controller.rb_cyclo.html +10 -0
  218. data/spec/fixtures/saikuro/app/controllers/users_controller.rb_cyclo.html +16 -0
  219. data/spec/fixtures/saikuro/index_cyclo.html +155 -0
  220. data/spec/fixtures/saikuro_sfiles/thing.rb_cyclo.html +11 -0
  221. data/spec/metric_fu/calculate_spec.rb +21 -0
  222. data/spec/metric_fu/configuration_spec.rb +90 -0
  223. data/spec/metric_fu/data_structures/line_numbers_spec.rb +63 -0
  224. data/spec/metric_fu/data_structures/location_spec.rb +110 -0
  225. data/spec/metric_fu/formatter/configuration_spec.rb +44 -0
  226. data/spec/metric_fu/formatter/html_spec.rb +138 -0
  227. data/spec/metric_fu/formatter/yaml_spec.rb +61 -0
  228. data/spec/metric_fu/formatter_spec.rb +49 -0
  229. data/spec/metric_fu/gem_version_spec.rb +12 -0
  230. data/spec/metric_fu/generator_spec.rb +130 -0
  231. data/spec/metric_fu/loader_spec.rb +13 -0
  232. data/spec/metric_fu/metric_spec.rb +46 -0
  233. data/spec/metric_fu/metrics/cane/configuration_spec.rb +22 -0
  234. data/spec/metric_fu/metrics/cane/generator_spec.rb +184 -0
  235. data/spec/metric_fu/metrics/churn/configuration_spec.rb +13 -0
  236. data/spec/metric_fu/metrics/churn/generator_spec.rb +64 -0
  237. data/spec/metric_fu/metrics/flay/configuration_spec.rb +13 -0
  238. data/spec/metric_fu/metrics/flay/generator_spec.rb +105 -0
  239. data/spec/metric_fu/metrics/flay/grapher_spec.rb +57 -0
  240. data/spec/metric_fu/metrics/flog/configuration_spec.rb +18 -0
  241. data/spec/metric_fu/metrics/flog/generator_spec.rb +77 -0
  242. data/spec/metric_fu/metrics/flog/grapher_spec.rb +107 -0
  243. data/spec/metric_fu/metrics/hotspots/analysis/analyzed_problems_spec.rb +104 -0
  244. data/spec/metric_fu/metrics/hotspots/analysis/analyzer_tables_spec.rb +71 -0
  245. data/spec/metric_fu/metrics/hotspots/analysis/ranking_spec.rb +30 -0
  246. data/spec/metric_fu/metrics/hotspots/analysis/rankings_spec.rb +97 -0
  247. data/spec/metric_fu/metrics/hotspots/analysis/table_spec.rb +6 -0
  248. data/spec/metric_fu/metrics/hotspots/generator_spec.rb +46 -0
  249. data/spec/metric_fu/metrics/hotspots/hotspot_analyzer_spec.rb +10 -0
  250. data/spec/metric_fu/metrics/hotspots/hotspot_spec.rb +16 -0
  251. data/spec/metric_fu/metrics/rails_best_practices/configuration_spec.rb +55 -0
  252. data/spec/metric_fu/metrics/rails_best_practices/generator_spec.rb +33 -0
  253. data/spec/metric_fu/metrics/rails_best_practices/grapher_spec.rb +62 -0
  254. data/spec/metric_fu/metrics/rcov/configuration_spec.rb +28 -0
  255. data/spec/metric_fu/metrics/rcov/generator_spec.rb +22 -0
  256. data/spec/metric_fu/metrics/rcov/grapher_spec.rb +57 -0
  257. data/spec/metric_fu/metrics/rcov/hotspot_spec.rb +20 -0
  258. data/spec/metric_fu/metrics/rcov/rcov_line_spec.rb +89 -0
  259. data/spec/metric_fu/metrics/rcov/simplecov_formatter_spec.rb +67 -0
  260. data/spec/metric_fu/metrics/reek/configuration_spec.rb +13 -0
  261. data/spec/metric_fu/metrics/reek/generator_spec.rb +203 -0
  262. data/spec/metric_fu/metrics/reek/grapher_spec.rb +66 -0
  263. data/spec/metric_fu/metrics/roodi/configuration_spec.rb +14 -0
  264. data/spec/metric_fu/metrics/roodi/generator_spec.rb +82 -0
  265. data/spec/metric_fu/metrics/roodi/grapher_spec.rb +57 -0
  266. data/spec/metric_fu/metrics/saikuro/configuration_spec.rb +25 -0
  267. data/spec/metric_fu/metrics/saikuro/generator_spec.rb +71 -0
  268. data/spec/metric_fu/metrics/stats/generator_spec.rb +96 -0
  269. data/spec/metric_fu/metrics/stats/grapher_spec.rb +69 -0
  270. data/spec/metric_fu/reporter_spec.rb +41 -0
  271. data/spec/metric_fu/reporting/graphs/graph_spec.rb +44 -0
  272. data/spec/metric_fu/reporting/graphs/grapher_spec.rb +24 -0
  273. data/spec/metric_fu/reporting/result_spec.rb +50 -0
  274. data/spec/metric_fu/run_spec.rb +197 -0
  275. data/spec/metric_fu/templates/configuration_spec.rb +51 -0
  276. data/spec/metric_fu/templates/metrics_template_spec.rb +11 -0
  277. data/spec/metric_fu/templates/report_spec.rb +15 -0
  278. data/spec/metric_fu/templates/template_spec.rb +233 -0
  279. data/spec/metric_fu/utility_spec.rb +12 -0
  280. data/spec/metric_fu_spec.rb +52 -0
  281. data/spec/quality_spec.rb +114 -0
  282. data/spec/shared/configured.rb +45 -0
  283. data/spec/shared/test_coverage.rb +95 -0
  284. data/spec/spec_helper.rb +46 -0
  285. data/spec/support/.metrics +4 -0
  286. data/spec/support/deferred_garbaged_collection.rb +33 -0
  287. data/spec/support/helper_methods.rb +32 -0
  288. data/spec/support/matcher_create_file.rb +37 -0
  289. data/spec/support/matcher_create_files.rb +43 -0
  290. data/spec/support/samples/reek/alfa.rb +1 -0
  291. data/spec/support/suite.rb +26 -0
  292. data/spec/support/test_fixtures.rb +37 -0
  293. data/spec/support/timeout.rb +7 -0
  294. data/spec/support/usage_test.rb +150 -0
  295. data/spec/usage_test_spec.rb +93 -0
  296. metadata +735 -0
@@ -0,0 +1,55 @@
1
+ MetricFu.reporting_require { "graphs/grapher" }
2
+ module MetricFu
3
+ class ReekGrapher < Grapher
4
+ attr_accessor :reek_count, :labels
5
+
6
+ def self.metric
7
+ :reek
8
+ end
9
+
10
+ def initialize
11
+ super
12
+ @reek_count = {}
13
+ @labels = {}
14
+ end
15
+
16
+ def get_metrics(metrics, date)
17
+ if metrics && metrics[:reek]
18
+ counter = @labels.size
19
+ @labels.update(@labels.size => date)
20
+
21
+ metrics[:reek][:matches].each do |reek_chunk|
22
+ reek_chunk[:code_smells].each do |code_smell|
23
+ # speaking of code smell...
24
+ @reek_count[code_smell[:type]] = [] if @reek_count[code_smell[:type]].nil?
25
+ if @reek_count[code_smell[:type]][counter].nil?
26
+ @reek_count[code_smell[:type]][counter] = 1
27
+ else
28
+ @reek_count[code_smell[:type]][counter] += 1
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def title
36
+ "Reek: code smells"
37
+ end
38
+
39
+ def data
40
+ @reek_count.map do |name, count|
41
+ [name, nil_counts_to_zero(count).join(",")]
42
+ end
43
+ end
44
+
45
+ def output_filename
46
+ "reek.js"
47
+ end
48
+
49
+ private
50
+
51
+ def nil_counts_to_zero(counts)
52
+ counts.map { |count| count || 0 }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,95 @@
1
+ # coding: utf-8
2
+ class MetricFu::ReekHotspot < MetricFu::Hotspot
3
+ # Note that in practice, the prefix reek__ is appended to each one
4
+ # This was a partially implemented idea to avoid column name collisions
5
+ # but it is only done in the ReekHotspot
6
+ COLUMNS = %w{type_name message value value_description comparable_message}
7
+
8
+ def columns
9
+ COLUMNS.map { |column| "#{name}__#{column}" }
10
+ end
11
+
12
+ def name
13
+ :reek
14
+ end
15
+
16
+ def map_strategy
17
+ :present
18
+ end
19
+
20
+ def reduce_strategy
21
+ :sum
22
+ end
23
+
24
+ def score_strategy
25
+ :percentile
26
+ end
27
+
28
+ def generate_records(data, table)
29
+ return if data == nil
30
+ data[:matches].each do |match|
31
+ file_path = match[:file_path]
32
+ match[:code_smells].each do |smell|
33
+ location = MetricFu::Location.for(smell[:method])
34
+ smell_type = smell[:type]
35
+ message = smell[:message]
36
+ table << {
37
+ "metric" => name, # important
38
+ "file_path" => file_path, # important
39
+ # NOTE: ReekHotspot is currently different than other hotspots with regard
40
+ # to column name. Note the COLUMNS constant and #columns method
41
+ "reek__message" => message,
42
+ "reek__type_name" => smell_type,
43
+ "reek__value" => parse_value(message),
44
+ "reek__value_description" => build_value_description(smell_type, message),
45
+ "reek__comparable_message" => comparable_message(smell_type, message),
46
+ "class_name" => location.class_name, # important
47
+ "method_name" => location.method_name, # important
48
+ }
49
+ end
50
+ end
51
+ end
52
+
53
+ def self.numeric_smell?(type)
54
+ ["Large Class", "Long Method", "Long Parameter List"].include?(type)
55
+ end
56
+
57
+ def present_group(group)
58
+ occurences = group.size
59
+ "found #{occurences} code smells"
60
+ end
61
+
62
+ private
63
+
64
+ def comparable_message(type_name, message)
65
+ if self.class.numeric_smell?(type_name)
66
+ match = message.match(/\d+/)
67
+ if match
68
+ match.pre_match + match.post_match
69
+ else
70
+ message
71
+ end
72
+ else
73
+ message
74
+ end
75
+ end
76
+
77
+ def build_value_description(type_name, message)
78
+ item_type = message.match(/\d+ (.*)$/)
79
+ if item_type
80
+ "number of #{item_type[1]} in #{type_name.downcase}"
81
+ else
82
+ nil
83
+ end
84
+ end
85
+
86
+ def parse_value(message)
87
+ # mf_debug "parsing #{message}"
88
+ match = message.match(/\d+/)
89
+ if match
90
+ match[0].to_i
91
+ else
92
+ nil
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,26 @@
1
+ module MetricFu
2
+ class MetricReek < Metric
3
+ def name
4
+ :reek
5
+ end
6
+
7
+ def default_run_options
8
+ {
9
+ dirs_to_reek: MetricFu::Io::FileSystem.directory("code_dirs"),
10
+ config_file_pattern: nil,
11
+ }
12
+ end
13
+
14
+ def has_graph?
15
+ true
16
+ end
17
+
18
+ def enable
19
+ super
20
+ end
21
+
22
+ def activate
23
+ super
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ <h3>Reek Results</h3>
2
+
3
+ <p><a href="http://github.com/troessner/reek">Reek</a> detects common code smells in ruby code.</p>
4
+
5
+ <%= render_partial 'graph', {:graph_name => 'reek'} %>
6
+
7
+ <table>
8
+ <tr>
9
+ <th>File Path</th>
10
+ <th>Method</th>
11
+ <th>Description</th>
12
+ <th>Type</th>
13
+ </tr>
14
+ <% count = 0 %>
15
+ <% @reek[:matches].each do |match| %>
16
+ <% match[:code_smells].each do |smell| %>
17
+ <tr class='<%= cycle("light", "dark", count) %>'>
18
+ <td><%= link_to_filename(match[:file_path]) %></td>
19
+ <td>
20
+ <%= smell[:method] %>
21
+ </td>
22
+ <td>
23
+ <%= smell[:message] %>
24
+ </td>
25
+ <td>
26
+ <%= smell[:type] %>
27
+ </td>
28
+ </tr>
29
+ <% count += 1 %>
30
+ <% end %>
31
+ <% end %>
32
+
33
+ </table>
34
+
35
+ <%= render_partial 'report_footer' %>
@@ -0,0 +1,40 @@
1
+ module MetricFu
2
+ class RoodiGenerator < Generator
3
+ def self.metric
4
+ :roodi
5
+ end
6
+
7
+ def emit
8
+ files_to_analyze = options[:dirs_to_roodi].map { |dir| Dir[File.join(dir, "**/*.rb")] }
9
+ files = remove_excluded_files(files_to_analyze.flatten)
10
+ config = options[:roodi_config] ? "-config=#{options[:roodi_config]}" : ""
11
+ args = "#{config} #{files.join(' ')}"
12
+ @output = run!(args)
13
+ end
14
+
15
+ def analyze
16
+ @output = MetricFu::Utility.strip_escape_codes(@output)
17
+ @matches = @output.chomp.split("\n").map { |m| m.split(" - ") }
18
+ total = @matches.pop
19
+ @matches.reject! { |array| array.size < 2 }
20
+ @matches.map! do |match|
21
+ file, line = match[0].split(":")
22
+ problem = match[1]
23
+ { file: file, line: line, problem: problem }
24
+ end
25
+ @roodi_results = { total: total, problems: @matches }
26
+ end
27
+
28
+ def to_h
29
+ { roodi: @roodi_results }
30
+ end
31
+
32
+ def per_file_info(out)
33
+ @matches.each do |match|
34
+ out[match[:file]] ||= {}
35
+ out[match[:file]][match[:line]] ||= []
36
+ out[match[:file]][match[:line]] << { type: :roodi, description: match[:problem] }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,37 @@
1
+ MetricFu.reporting_require { "graphs/grapher" }
2
+ module MetricFu
3
+ class RoodiGrapher < Grapher
4
+ attr_accessor :roodi_count, :labels
5
+
6
+ def self.metric
7
+ :roodi
8
+ end
9
+
10
+ def initialize
11
+ super
12
+ @roodi_count = []
13
+ @labels = {}
14
+ end
15
+
16
+ def get_metrics(metrics, date)
17
+ if metrics && metrics[:roodi]
18
+ @roodi_count.push(metrics[:roodi][:problems].size)
19
+ @labels.update(@labels.size => date)
20
+ end
21
+ end
22
+
23
+ def title
24
+ "Roodi: design problems"
25
+ end
26
+
27
+ def data
28
+ [
29
+ ["roodi", @roodi_count.join(",")]
30
+ ]
31
+ end
32
+
33
+ def output_filename
34
+ "roodi.js"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,39 @@
1
+ class MetricFu::RoodiHotspot < MetricFu::Hotspot
2
+ COLUMNS = %w{problems}
3
+
4
+ def columns
5
+ COLUMNS
6
+ end
7
+
8
+ def name
9
+ :roodi
10
+ end
11
+
12
+ def map_strategy
13
+ :present
14
+ end
15
+
16
+ def reduce_strategy
17
+ :sum
18
+ end
19
+
20
+ def score_strategy
21
+ :percentile
22
+ end
23
+
24
+ def generate_records(data, table)
25
+ return if data == nil
26
+ Array(data[:problems]).each do |problem|
27
+ table << {
28
+ "metric" => name,
29
+ "problems" => problem[:problem],
30
+ "file_path" => problem[:file]
31
+ }
32
+ end
33
+ end
34
+
35
+ def present_group(group)
36
+ occurences = group.size
37
+ "found #{occurences} design problems"
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ module MetricFu
2
+ class MetricRoodi < Metric
3
+ def name
4
+ :roodi
5
+ end
6
+
7
+ def default_run_options
8
+ { dirs_to_roodi: MetricFu::Io::FileSystem.directory("code_dirs"),
9
+ roodi_config: "#{MetricFu::Io::FileSystem.directory('root_directory')}/config/roodi_config.yml" }
10
+ end
11
+
12
+ def has_graph?
13
+ true
14
+ end
15
+
16
+ def enable
17
+ super
18
+ end
19
+
20
+ def activate
21
+ super
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ <h3>Roodi Results</h3>
2
+
3
+ <p><a href="http://roodi.rubyforge.org/">Roodi</a> parses your Ruby code and warns you about design issues you have based on the checks that is has configured.</p>
4
+
5
+ <%= render_partial 'graph', {:graph_name => 'roodi'} %>
6
+
7
+ <table>
8
+ <tr>
9
+ <th>File Path</th>
10
+ <th>Warning</th>
11
+ </tr>
12
+ <% count = 0 %>
13
+ <% @roodi[:problems].each do |problem| %>
14
+ <tr class='<%= cycle("light", "dark", count) %>'>
15
+ <td><%= link_to_filename(problem[:file], problem[:line]) %></td>
16
+ <td><%= problem[:problem] %></td>
17
+ </tr>
18
+ <% count += 1 %>
19
+ <% end %>
20
+ </table>
21
+
22
+ <%= render_partial 'report_footer' %>
@@ -0,0 +1,145 @@
1
+ # encoding: utf-8
2
+ MetricFu.lib_require { "utility" }
3
+ MetricFu.metrics_require { "saikuro/scratch_file" }
4
+ MetricFu.metrics_require { "saikuro/parsing_element" }
5
+ MetricFu.data_structures_require { "line_numbers" }
6
+ module MetricFu
7
+ class SaikuroGenerator < MetricFu::Generator
8
+ def self.metric
9
+ :saikuro
10
+ end
11
+
12
+ def emit
13
+ options_string = options.inject("") do |options, option|
14
+ option[0] == :input_directory ? options : options + "--#{option.join(' ')} "
15
+ end
16
+
17
+ options[:input_directory].each do |input_dir|
18
+ options_string += "--input_directory #{input_dir} "
19
+ end
20
+
21
+ @output = run!(options_string)
22
+ end
23
+
24
+ def analyze
25
+ @files = sort_files(assemble_files)
26
+ @classes = sort_classes(assemble_classes(@files))
27
+ @meths = sort_methods(assemble_methods(@files))
28
+ end
29
+
30
+ def to_h
31
+ @saikuro_data = {
32
+ files: files_with_relative_paths(@files),
33
+ classes: @classes.map(&:to_h),
34
+ methods: @meths.map(&:to_h),
35
+ }
36
+ clear_scratch_files!
37
+ { saikuro: @saikuro_data }
38
+ end
39
+
40
+ def per_file_info(out)
41
+ @saikuro_data[:files].each do |file_data|
42
+ filename = file_data[:filename]
43
+ next if erb_file?(filename) || file_not_exists?(filename)
44
+ next unless line_numbers = line_numbers_from_file(filename)
45
+
46
+ build_output_from_line_numbers(out, line_numbers, file_data)
47
+ end
48
+ end
49
+
50
+ def build_output_from_line_numbers(out, line_numbers, file_data)
51
+ filename = file_data[:filename]
52
+ output = out[filename]
53
+ method_data_for_file_data(file_data) do |method_data|
54
+ line = line_numbers.start_line_for_method(method_data[:name]).to_s
55
+ result = {
56
+ type: :saikuro,
57
+ description: "Complexity #{method_data[:complexity]}"
58
+ }
59
+ output[line] << result
60
+ end
61
+ out
62
+ end
63
+
64
+ def line_numbers_from_file(filename)
65
+ MetricFu::LineNumbers.new(File.read(filename))
66
+ rescue StandardError => e
67
+ raise e unless e.message =~ /you shouldn't be able to get here/
68
+ mf_log "ruby_parser blew up while trying to parse #{file_path}. You won't have method level Saikuro information for this file."
69
+ end
70
+
71
+ def method_data_for_file_data(file_data, &_block)
72
+ return unless block_given?
73
+ file_data[:classes].each do |class_data|
74
+ class_data[:methods].each do |method_data|
75
+ yield method_data
76
+ end
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def erb_file?(filename)
83
+ File.extname(filename) == ".erb"
84
+ end
85
+
86
+ def file_not_exists?(filename)
87
+ !File.exists?(filename)
88
+ end
89
+
90
+ def sort_methods(methods)
91
+ methods.sort_by { |method| method.complexity.to_i }.reverse
92
+ end
93
+
94
+ def assemble_methods(files)
95
+ methods = []
96
+ files.each do |file|
97
+ file.elements.each do |element|
98
+ element.defs.each do |defn|
99
+ defn.name = "#{element.name}##{defn.name}"
100
+ methods << defn
101
+ end
102
+ end
103
+ end
104
+ methods
105
+ end
106
+
107
+ def sort_classes(classes)
108
+ classes.sort_by { |k| k.complexity.to_i }.reverse
109
+ end
110
+
111
+ def assemble_classes(files)
112
+ files.map(&:elements).flatten
113
+ end
114
+
115
+ def sort_files(files)
116
+ files.sort_by do |file|
117
+ file.elements.
118
+ max { |a, b| a.complexity.to_i <=> b.complexity.to_i }.
119
+ complexity.to_i
120
+ end.reverse
121
+ end
122
+
123
+ def assemble_files
124
+ SaikuroScratchFile.assemble_files(Dir.glob("#{metric_directory}/**/*.html"))
125
+ end
126
+
127
+ def files_with_relative_paths(files)
128
+ files.map do |file|
129
+ file_hash = file.to_h
130
+ file_hash[:filename] = file_relative_path(file)
131
+ file_hash
132
+ end.to_a
133
+ end
134
+
135
+ def file_relative_path(file)
136
+ filepath = file.filepath
137
+ path = filepath.gsub(/^#{metric_directory}\//, "")
138
+ "#{path}/#{file.filename}"
139
+ end
140
+
141
+ def clear_scratch_files!
142
+ MetricFu::Utility.rm_rf(metric_directory)
143
+ end
144
+ end
145
+ end