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,61 @@
1
+ module MetricFu
2
+ class MetricRcov < Metric
3
+ def name
4
+ :rcov
5
+ end
6
+
7
+ def default_run_options
8
+ {
9
+ environment: "test",
10
+ test_files: Dir["{spec,test}/**/*_{spec,test}.rb"],
11
+ rcov_opts: rcov_opts,
12
+ external: nil,
13
+ }
14
+ end
15
+
16
+ def coverage_file=(coverage_file)
17
+ configured_run_options.update(external: coverage_file)
18
+ end
19
+
20
+ def has_graph?
21
+ true
22
+ end
23
+
24
+ def enable
25
+ if external_coverage_file?
26
+ super
27
+ else
28
+ mf_debug("RCov is not available. See README")
29
+ end
30
+ end
31
+
32
+ def activate
33
+ super
34
+ end
35
+
36
+ def external_coverage_file?
37
+ if coverage_file = run_options[:external]
38
+ File.exist?(coverage_file) ||
39
+ mf_log("Configured RCov file #{coverage_file.inspect} does not exist")
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def rcov_opts
48
+ rcov_opts = [
49
+ "--sort coverage",
50
+ "--no-html",
51
+ "--text-coverage",
52
+ "--no-color",
53
+ "--profile",
54
+ "--exclude-only '.*'",
55
+ '--include-file "\Aapp,\Alib"'
56
+ ]
57
+ rcov_opts << "-Ispec" if File.exist?("spec")
58
+ rcov_opts
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,149 @@
1
+ module MetricFu
2
+ class RCovFormatCoverage
3
+ NEW_FILE_MARKER = /^={80}$/.freeze
4
+
5
+ def initialize(rcov_text)
6
+ fail "no rcov text" if rcov_text.nil?
7
+ @rcov_text = rcov_text
8
+ end
9
+
10
+ def to_h
11
+ rcov_text = @rcov_text.split(NEW_FILE_MARKER)
12
+
13
+ rcov_text.shift # Throw away the first entry - it's the execution time etc.
14
+
15
+ files = assemble_files(rcov_text)
16
+
17
+ TestCoverage.new(files).to_h
18
+ end
19
+
20
+ private
21
+
22
+ def assemble_files(rcov_text)
23
+ files = {}
24
+ rcov_text.each_slice(2) { |out| files[out.first.strip] = out.last }
25
+ files.each_pair { |fname, content| files[fname] = content.split("\n") }
26
+ files.each_pair do |fname, content|
27
+ content.map! do |raw_line|
28
+ covered_line = if raw_line.start_with?("--")
29
+ nil # simplecov ignores some lines
30
+ elsif raw_line.start_with?("!!")
31
+ 0
32
+ else
33
+ 1
34
+ end
35
+ RCovLine.new(raw_line[3..-1], covered_line).to_h
36
+ end
37
+ content.reject! { |line| line[:content].to_s == "" }
38
+ files[fname] = { lines: content }
39
+ end
40
+ files
41
+ end
42
+
43
+ class TestCoverage
44
+ def initialize(filename_content)
45
+ @files = filename_content
46
+ @global_total_lines = 0
47
+ @global_total_lines_run = 0
48
+ end
49
+
50
+ def to_h
51
+ @test_coverage ||= begin
52
+ add_coverage_percentage(@files)
53
+ add_method_data(@files)
54
+ add_global_percent_run(@files, @global_total_lines, @global_total_lines_run)
55
+ @files
56
+ end
57
+ end
58
+
59
+ def self.floating_percent(numerator, denominator)
60
+ (numerator * 100.0) / denominator.to_f
61
+ end
62
+
63
+ def self.integer_percent(numerator, denominator)
64
+ ::MetricFu::Calculate.integer_percent(numerator, denominator)
65
+ end
66
+
67
+ def self.percent_run(lines)
68
+ line_coverage = RCovLine.line_coverage(lines)
69
+ covered_lines = RCovLine.covered_lines(line_coverage)
70
+ ignored_lines = RCovLine.ignored_lines(line_coverage)
71
+ relevant_lines = lines.count - ignored_lines
72
+ if block_given?
73
+ yield covered_lines, relevant_lines
74
+ else
75
+ floating_percent(covered_lines, relevant_lines)
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ # TODO: remove multiple side effects
82
+ # sets global ivars and
83
+ # modifies the param passed in
84
+ def add_coverage_percentage(files)
85
+ files.each_pair do |fname, content|
86
+ lines = content[:lines]
87
+ percent_run =
88
+ self.class.percent_run(lines) do |covered, relevant|
89
+ @global_total_lines_run += covered
90
+ @global_total_lines += relevant
91
+ self.class.integer_percent(covered, relevant)
92
+ end
93
+ files[fname][:percent_run] = percent_run
94
+ end
95
+ end
96
+
97
+ def add_global_percent_run(test_coverage, total_lines, total_lines_run)
98
+ percentage = self.class.floating_percent(total_lines_run, total_lines)
99
+ test_coverage.update(
100
+ global_percent_run: round_to_tenths(percentage)
101
+ )
102
+ end
103
+
104
+ def add_method_data(test_coverage)
105
+ test_coverage.each_pair do |file_path, info|
106
+ file_contents = ""
107
+ coverage = []
108
+
109
+ info[:lines].each_with_index do |line, _index|
110
+ file_contents << "#{line[:content]}\n"
111
+ coverage << line[:was_run]
112
+ end
113
+
114
+ begin
115
+ line_numbers = MetricFu::LineNumbers.new(file_contents)
116
+ rescue StandardError => e
117
+ raise e unless e.message =~ /you shouldn't be able to get here/
118
+ mf_log "ruby_parser blew up while trying to parse #{file_path}. You won't have method level TestCoverage information for this file."
119
+ next
120
+ end
121
+
122
+ method_coverage_map = {}
123
+ coverage.each_with_index do |covered, index|
124
+ line_number = index + 1
125
+ if line_numbers.in_method?(line_number)
126
+ method_name = line_numbers.method_at_line(line_number)
127
+ method_coverage_map[method_name] ||= {}
128
+ method_coverage_map[method_name][:total] ||= 0
129
+ method_coverage_map[method_name][:total] += 1
130
+ method_coverage_map[method_name][:uncovered] ||= 0
131
+ method_coverage_map[method_name][:uncovered] += 1 if !covered
132
+ end
133
+ end
134
+
135
+ test_coverage[file_path][:methods] = {}
136
+
137
+ method_coverage_map.each do |method_name, coverage_data|
138
+ test_coverage[file_path][:methods][method_name] = (coverage_data[:uncovered] / coverage_data[:total].to_f) * 100.0
139
+ end
140
+ end
141
+ end
142
+
143
+ def round_to_tenths(decimal)
144
+ decimal = 0.0 if decimal.to_s.eql?("NaN")
145
+ (decimal * 10).round / 10.0
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,48 @@
1
+ module MetricFu
2
+ class RCovLine
3
+ attr_accessor :content, :was_run
4
+
5
+ def initialize(content, was_run)
6
+ @content = content
7
+ @was_run = was_run
8
+ end
9
+
10
+ def to_h
11
+ { content: @content, was_run: @was_run }
12
+ end
13
+
14
+ def covered?
15
+ @was_run == 1
16
+ end
17
+
18
+ def missed?
19
+ @was_run == 0
20
+ end
21
+
22
+ def ignored?
23
+ @was_run.nil?
24
+ end
25
+
26
+ def self.line_coverage(lines)
27
+ lines.map { |line| line[:was_run] }
28
+ end
29
+
30
+ def self.covered_lines(line_coverage)
31
+ line_coverage.count(1)
32
+ end
33
+
34
+ def self.missed_lines(line_coverage)
35
+ line_coverage.count(0)
36
+ end
37
+
38
+ def self.ignored_lines(line_coverage)
39
+ line_coverage.count(nil)
40
+ end
41
+
42
+ def css_class
43
+ return "rcov_not_run" if missed?
44
+
45
+ "rcov_run"
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ <style data-file="rcov">
2
+ <%= inline_css("css/rcov.css") %>
3
+ </style>
4
+ <h3>Rcov Code Coverage Results</h3>
5
+
6
+ <p>C0 code coverage information.</p>
7
+
8
+ <%= render_partial 'graph', {:graph_name => 'rcov'} %>
9
+
10
+ <p>Total Coverage: <%= @rcov.delete(:global_percent_run) %>% </p>
11
+ <table>
12
+ <tr>
13
+ <th>File Path</th>
14
+ <th>Percent run</th>
15
+ </tr>
16
+ <% count = 0 %>
17
+ <% @rcov.sort_by{ |k,v| v[:percent_run] }.each do |fname, file| %>
18
+ <tr>
19
+ <td><a href="#<%= fname.gsub(/[^a-z]+/, '_') %>"><%= fname %></a></td>
20
+ <td><%= file[:percent_run] %></td>
21
+ </tr>
22
+ <% count += 1 %>
23
+ <% end %>
24
+ </table>
25
+
26
+ <% @rcov.sort_by{ |k,v| v[:percent_run] }.each do |fname, file| %>
27
+ <h2 id="<%= fname.gsub(/[^a-z]+/, '_') %>"> <%= fname %></h2>
28
+ <div class="rcov_overflow">
29
+ <table class="rcov_code">
30
+ <% file[:lines].each_with_index do |line, index| %>
31
+ <tr>
32
+ <% rcov_line = RCovLine.new(line[:content], line[:was_run]) %>
33
+ <td class="<%= rcov_line.css_class %>"><%= link_to_filename(fname, index + 1, "<pre>#{line[:content]}</pre>") %></td>
34
+ </tr>
35
+ <% end %>
36
+ </table>
37
+ </div>
38
+ <% end %>
39
+
40
+ <%= render_partial 'report_footer' %>
@@ -0,0 +1,74 @@
1
+ if defined?(JRUBY_VERSION)
2
+ if ENV["JRUBY_OPTS"].to_s !~ /-Xcli.debug=true/
3
+ warn "Coverage may be inaccurate; Try setting JRUBY_OPTS=\"-Xcli.debug=true --debug\""
4
+ # see https://github.com/metricfu/metric_fu/pull/226
5
+ # https://github.com/jruby/jruby/issues/1196
6
+ # https://jira.codehaus.org/browse/JRUBY-6106
7
+ # https://github.com/colszowka/simplecov/issues/86
8
+ end
9
+ end
10
+ require "simplecov"
11
+ require "metric_fu/logger"
12
+ require_relative "external_client"
13
+ require_relative "rcov_format_coverage"
14
+
15
+ class SimpleCov::Formatter::MetricFu
16
+ def format(result)
17
+ rcov_text = FormatLikeRCov.new(result).format
18
+ client = MetricFu::RCovTestCoverageClient.new(coverage_file_path)
19
+ client.post_results(rcov_text)
20
+ end
21
+
22
+ attr_writer :coverage_file_path
23
+
24
+ def coverage_file_path
25
+ @coverage_file_path || self.coverage_file_path = default_coverage_file_path
26
+ end
27
+
28
+ def default_coverage_file_path
29
+ File.join(SimpleCov.root, "coverage", "rcov", output_file_name)
30
+ end
31
+
32
+ # TODO: Read in from legacy coverage/rcov/rcov.txt path, when set
33
+ # write to date-specific report file, read from if present
34
+ # e.g.
35
+ # MetricFu::Metric.get_metric(:rcov).run_options[:output_directory]
36
+ # or
37
+ # metric_directory = MetricFu::Io::FileSystem.scratch_directory('Ymd-coverage')
38
+ # MetricFu::Utility.mkdir_p(metric_directory, :verbose => false)
39
+ # @note legacy file name is 'rcov.txt'
40
+ # going forward, the file name will be in a date-stamped
41
+ # format like for all other reported metrics.
42
+ def output_file_name
43
+ "rcov.txt"
44
+ end
45
+
46
+ # report should reference file used to build it
47
+ class FormatLikeRCov
48
+ def initialize(result)
49
+ @result = result
50
+ end
51
+
52
+ def format
53
+ content = "metric_fu shift the first line\n"
54
+ @result.source_files.each do |source_file|
55
+ content << "=" * 80
56
+ content << "\n #{simple_file_name(source_file)}\n"
57
+ content << "=" * 80
58
+ content << "\n"
59
+ source_file.lines.each do |line|
60
+ content << "!!" if line.missed?
61
+ content << "--" if line.never? || line.skipped?
62
+ content << " " if line.covered?
63
+ content << " #{line.src.chomp}\n"
64
+ end
65
+ content << "\n"
66
+ end
67
+ content
68
+ end
69
+
70
+ def simple_file_name(source_file)
71
+ source_file.filename.gsub(SimpleCov.root, ".")
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,94 @@
1
+ module MetricFu
2
+ class ReekGenerator < Generator
3
+ def self.metric
4
+ :reek
5
+ end
6
+
7
+ def emit
8
+ files = files_to_analyze
9
+ if files.empty?
10
+ mf_log "Skipping Reek, no files found to analyze"
11
+ @output = run!([], config_files)
12
+ else
13
+ @output = run!(files, config_files)
14
+ end
15
+ end
16
+
17
+ def run!(files, config_files)
18
+ files.map do |file|
19
+ examiner.new(File.new(file), filter_by_smells: config_files)
20
+ end
21
+ end
22
+
23
+ def analyze
24
+ @matches = @output.flat_map(&:smells).group_by(&:source).collect do |file_path, smells|
25
+ { file_path: file_path,
26
+ code_smells: analyze_smells(smells) }
27
+ end
28
+ end
29
+
30
+ def to_h
31
+ { reek: { matches: @matches } }
32
+ end
33
+
34
+ def per_file_info(out)
35
+ @matches.each do |file_data|
36
+ file_path = file_data[:file_path]
37
+ next if File.extname(file_path) =~ /\.erb|\.html|\.haml/
38
+ begin
39
+ line_numbers = MetricFu::LineNumbers.new(File.read(file_path), file_path)
40
+ rescue StandardError => e
41
+ raise e unless e.message =~ /you shouldn't be able to get here/
42
+ mf_log "ruby_parser blew up while trying to parse #{file_path}. You won't have method level reek information for this file."
43
+ next
44
+ end
45
+
46
+ file_data[:code_smells].each do |smell_data|
47
+ line = line_numbers.start_line_for_method(smell_data[:method])
48
+ out[file_data[:file_path]][line.to_s] << { type: :reek,
49
+ description: "#{smell_data[:type]} - #{smell_data[:message]}" }
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def files_to_analyze
57
+ dirs_to_reek = options[:dirs_to_reek]
58
+ files_to_reek = dirs_to_reek.map { |dir| Dir[File.join(dir, "**", "*.rb")] }.flatten
59
+ remove_excluded_files(files_to_reek)
60
+ end
61
+
62
+ # TODO: Check that specified line config file exists
63
+ def config_files
64
+ Array(options[:config_file_pattern])
65
+ end
66
+
67
+ def analyze_smells(smells)
68
+ smells.collect(&method(:smell_data))
69
+ end
70
+
71
+ def smell_data(smell)
72
+ { method: smell.context,
73
+ message: smell.message,
74
+ type: smell_type(smell),
75
+ lines: smell.lines }
76
+ end
77
+
78
+ def smell_type(smell)
79
+ return smell.subclass if smell.respond_to?(:subclass)
80
+
81
+ smell.smell_type
82
+ end
83
+
84
+ def examiner
85
+ require "reek"
86
+ # To load any changing dependencies such as "reek/configuration/app_configuration"
87
+ # Added in 1.6.0 https://github.com/troessner/reek/commit/7f4ed2be442ca926e08ccc41945e909e8f710947
88
+ # But not always loaded
89
+ require "reek/cli/application"
90
+
91
+ Reek.const_defined?(:Examiner) ? Reek.const_get(:Examiner) : Reek.const_get(:Core).const_get(:Examiner)
92
+ end
93
+ end
94
+ end