code_metric_fu 4.14.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.
- checksums.yaml +7 -0
- data/.gitignore +28 -0
- data/.metrics +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +15 -0
- data/.rubocop_todo.yml +69 -0
- data/.simplecov +74 -0
- data/.travis.yml +22 -0
- data/.yardopts +4 -0
- data/AUTHORS +12 -0
- data/CONTRIBUTING.md +47 -0
- data/CONTRIBUTORS +76 -0
- data/DEV.md +76 -0
- data/Gemfile +74 -0
- data/Guardfile +30 -0
- data/HISTORY.md +705 -0
- data/MIT-LICENSE +22 -0
- data/README.md +299 -0
- data/Rakefile +27 -0
- data/TODO.md +118 -0
- data/appveyor.yml +31 -0
- data/bin/metric_fu +9 -0
- data/bin/mf-cane +10 -0
- data/bin/mf-churn +10 -0
- data/bin/mf-flay +10 -0
- data/bin/mf-reek +10 -0
- data/bin/mf-roodi +10 -0
- data/bin/mf-saikuro +10 -0
- data/certs/bf4.pem +22 -0
- data/checksum/.gitkeep +0 -0
- data/checksum/metric_fu-4.10.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.11.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.11.1.gem.sha512 +1 -0
- data/checksum/metric_fu-4.11.2.gem.sha512 +1 -0
- data/checksum/metric_fu-4.11.3.gem.sha512 +1 -0
- data/checksum/metric_fu-4.11.4.gem.sha512 +1 -0
- data/checksum/metric_fu-4.12.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.2.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.2.1.gem.sha512 +1 -0
- data/checksum/metric_fu-4.3.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.3.1.gem.sha512 +1 -0
- data/checksum/metric_fu-4.4.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.4.1.gem.sha512 +1 -0
- data/checksum/metric_fu-4.4.2.gem.sha512 +1 -0
- data/checksum/metric_fu-4.4.3.gem.sha512 +1 -0
- data/checksum/metric_fu-4.4.4.gem.sha512 +1 -0
- data/checksum/metric_fu-4.5.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.5.1.gem.sha512 +1 -0
- data/checksum/metric_fu-4.5.2.gem.sha512 +1 -0
- data/checksum/metric_fu-4.6.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.7.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.7.1.gem.sha512 +1 -0
- data/checksum/metric_fu-4.7.2.gem.sha512 +1 -0
- data/checksum/metric_fu-4.7.3.gem.sha512 +1 -0
- data/checksum/metric_fu-4.7.4.gem.sha512 +1 -0
- data/checksum/metric_fu-4.8.0.gem.sha512 +1 -0
- data/checksum/metric_fu-4.9.0.gem.sha512 +1 -0
- data/config/roodi_config.yml +22 -0
- data/config/rubocop.yml +269 -0
- data/gem_tasks/build.rake +197 -0
- data/gem_tasks/rubocop.rake +10 -0
- data/gem_tasks/usage_test.rake +19 -0
- data/gem_tasks/yard.rake +24 -0
- data/lib/metric_fu/calculate.rb +10 -0
- data/lib/metric_fu/cli/client.rb +26 -0
- data/lib/metric_fu/cli/helper.rb +80 -0
- data/lib/metric_fu/cli/parser.rb +138 -0
- data/lib/metric_fu/configuration.rb +150 -0
- data/lib/metric_fu/constantize.rb +57 -0
- data/lib/metric_fu/data_structures/line_numbers.rb +112 -0
- data/lib/metric_fu/data_structures/location.rb +110 -0
- data/lib/metric_fu/data_structures/sexp_node.rb +107 -0
- data/lib/metric_fu/environment.rb +129 -0
- data/lib/metric_fu/errors/analysis_error.rb +4 -0
- data/lib/metric_fu/formatter/html.rb +96 -0
- data/lib/metric_fu/formatter/syntax.rb +45 -0
- data/lib/metric_fu/formatter/yaml.rb +18 -0
- data/lib/metric_fu/formatter.rb +40 -0
- data/lib/metric_fu/gem_run.rb +70 -0
- data/lib/metric_fu/gem_version.rb +92 -0
- data/lib/metric_fu/generator.rb +135 -0
- data/lib/metric_fu/io.rb +132 -0
- data/lib/metric_fu/loader.rb +105 -0
- data/lib/metric_fu/logger.rb +62 -0
- data/lib/metric_fu/logging/mf_debugger.rb +23 -0
- data/lib/metric_fu/metric.rb +143 -0
- data/lib/metric_fu/metrics/cane/generator.rb +95 -0
- data/lib/metric_fu/metrics/cane/grapher.rb +37 -0
- data/lib/metric_fu/metrics/cane/metric.rb +34 -0
- data/lib/metric_fu/metrics/cane/report.html.erb +87 -0
- data/lib/metric_fu/metrics/cane/violations.rb +46 -0
- data/lib/metric_fu/metrics/churn/generator.rb +37 -0
- data/lib/metric_fu/metrics/churn/hotspot.rb +43 -0
- data/lib/metric_fu/metrics/churn/metric.rb +29 -0
- data/lib/metric_fu/metrics/churn/report.html.erb +58 -0
- data/lib/metric_fu/metrics/flay/generator.rb +51 -0
- data/lib/metric_fu/metrics/flay/grapher.rb +37 -0
- data/lib/metric_fu/metrics/flay/hotspot.rb +52 -0
- data/lib/metric_fu/metrics/flay/metric.rb +28 -0
- data/lib/metric_fu/metrics/flay/report.html.erb +29 -0
- data/lib/metric_fu/metrics/flog/generator.rb +113 -0
- data/lib/metric_fu/metrics/flog/grapher.rb +77 -0
- data/lib/metric_fu/metrics/flog/hotspot.rb +46 -0
- data/lib/metric_fu/metrics/flog/metric.rb +29 -0
- data/lib/metric_fu/metrics/flog/report.html.erb +50 -0
- data/lib/metric_fu/metrics/hotspots/analysis/analyzed_problems.rb +34 -0
- data/lib/metric_fu/metrics/hotspots/analysis/analyzer_tables.rb +114 -0
- data/lib/metric_fu/metrics/hotspots/analysis/grouping.rb +23 -0
- data/lib/metric_fu/metrics/hotspots/analysis/groupings.rb +12 -0
- data/lib/metric_fu/metrics/hotspots/analysis/problems.rb +20 -0
- data/lib/metric_fu/metrics/hotspots/analysis/ranked_problem_location.rb +70 -0
- data/lib/metric_fu/metrics/hotspots/analysis/ranking.rb +29 -0
- data/lib/metric_fu/metrics/hotspots/analysis/rankings.rb +91 -0
- data/lib/metric_fu/metrics/hotspots/analysis/record.rb +32 -0
- data/lib/metric_fu/metrics/hotspots/analysis/scoring_strategies.rb +24 -0
- data/lib/metric_fu/metrics/hotspots/analysis/table.rb +67 -0
- data/lib/metric_fu/metrics/hotspots/generator.rb +40 -0
- data/lib/metric_fu/metrics/hotspots/hotspot.rb +87 -0
- data/lib/metric_fu/metrics/hotspots/hotspot_analyzer.rb +61 -0
- data/lib/metric_fu/metrics/hotspots/metric.rb +20 -0
- data/lib/metric_fu/metrics/hotspots/report.html.erb +60 -0
- data/lib/metric_fu/metrics/rails_best_practices/generator.rb +47 -0
- data/lib/metric_fu/metrics/rails_best_practices/grapher.rb +38 -0
- data/lib/metric_fu/metrics/rails_best_practices/metric.rb +31 -0
- data/lib/metric_fu/metrics/rails_best_practices/report.html.erb +22 -0
- data/lib/metric_fu/metrics/rcov/external_client.rb +22 -0
- data/lib/metric_fu/metrics/rcov/generator.rb +75 -0
- data/lib/metric_fu/metrics/rcov/grapher.rb +37 -0
- data/lib/metric_fu/metrics/rcov/hotspot.rb +46 -0
- data/lib/metric_fu/metrics/rcov/metric.rb +61 -0
- data/lib/metric_fu/metrics/rcov/rcov_format_coverage.rb +149 -0
- data/lib/metric_fu/metrics/rcov/rcov_line.rb +48 -0
- data/lib/metric_fu/metrics/rcov/report.html.erb +40 -0
- data/lib/metric_fu/metrics/rcov/simplecov_formatter.rb +74 -0
- data/lib/metric_fu/metrics/reek/generator.rb +97 -0
- data/lib/metric_fu/metrics/reek/grapher.rb +55 -0
- data/lib/metric_fu/metrics/reek/hotspot.rb +95 -0
- data/lib/metric_fu/metrics/reek/metric.rb +26 -0
- data/lib/metric_fu/metrics/reek/report.html.erb +35 -0
- data/lib/metric_fu/metrics/roodi/generator.rb +41 -0
- data/lib/metric_fu/metrics/roodi/grapher.rb +37 -0
- data/lib/metric_fu/metrics/roodi/hotspot.rb +39 -0
- data/lib/metric_fu/metrics/roodi/metric.rb +24 -0
- data/lib/metric_fu/metrics/roodi/report.html.erb +22 -0
- data/lib/metric_fu/metrics/saikuro/generator.rb +145 -0
- data/lib/metric_fu/metrics/saikuro/hotspot.rb +51 -0
- data/lib/metric_fu/metrics/saikuro/metric.rb +31 -0
- data/lib/metric_fu/metrics/saikuro/parsing_element.rb +37 -0
- data/lib/metric_fu/metrics/saikuro/report.html.erb +71 -0
- data/lib/metric_fu/metrics/saikuro/scratch_file.rb +108 -0
- data/lib/metric_fu/metrics/stats/generator.rb +82 -0
- data/lib/metric_fu/metrics/stats/grapher.rb +40 -0
- data/lib/metric_fu/metrics/stats/hotspot.rb +35 -0
- data/lib/metric_fu/metrics/stats/metric.rb +28 -0
- data/lib/metric_fu/metrics/stats/report.html.erb +44 -0
- data/lib/metric_fu/reporter.rb +37 -0
- data/lib/metric_fu/reporting/graphs/graph.rb +69 -0
- data/lib/metric_fu/reporting/graphs/grapher.rb +66 -0
- data/lib/metric_fu/reporting/result.rb +59 -0
- data/lib/metric_fu/run.rb +82 -0
- data/lib/metric_fu/tasks/metric_fu.rake +54 -0
- data/lib/metric_fu/templates/_gem_info.html.erb +8 -0
- data/lib/metric_fu/templates/_graph.html.erb +2 -0
- data/lib/metric_fu/templates/_report_footer.html.erb +1 -0
- data/lib/metric_fu/templates/configuration.rb +25 -0
- data/lib/metric_fu/templates/css/bluff.css +15 -0
- data/lib/metric_fu/templates/css/buttons.css +82 -0
- data/lib/metric_fu/templates/css/default.css +43 -0
- data/lib/metric_fu/templates/css/integrity.css +337 -0
- data/lib/metric_fu/templates/css/rcov.css +32 -0
- data/lib/metric_fu/templates/css/reset.css +7 -0
- data/lib/metric_fu/templates/css/syntax.css +19 -0
- data/lib/metric_fu/templates/index.html.erb +13 -0
- data/lib/metric_fu/templates/javascripts/bluff-min.js +1 -0
- data/lib/metric_fu/templates/javascripts/bluff_graph.js +15 -0
- data/lib/metric_fu/templates/javascripts/excanvas.js +35 -0
- data/lib/metric_fu/templates/javascripts/highcharts.js +294 -0
- data/lib/metric_fu/templates/javascripts/highcharts_graph.js +38 -0
- data/lib/metric_fu/templates/javascripts/js-class.js +1 -0
- data/lib/metric_fu/templates/javascripts/standalone-framework.js +17 -0
- data/lib/metric_fu/templates/javascripts/utils.js +9 -0
- data/lib/metric_fu/templates/layout.html.erb +41 -0
- data/lib/metric_fu/templates/metrics_template.rb +86 -0
- data/lib/metric_fu/templates/report.html.erb +31 -0
- data/lib/metric_fu/templates/report.rb +41 -0
- data/lib/metric_fu/templates/template.rb +247 -0
- data/lib/metric_fu/utility.rb +79 -0
- data/lib/metric_fu/version.rb +9 -0
- data/lib/metric_fu.rb +143 -0
- data/metric_fu.gemspec +72 -0
- data/spec/capture_warnings.rb +55 -0
- data/spec/cli/helper_spec.rb +165 -0
- data/spec/dummy/.gitignore +1 -0
- data/spec/dummy/.gitkeep +0 -0
- data/spec/dummy/.metrics +4 -0
- data/spec/dummy/lib/.gitkeep +0 -0
- data/spec/dummy/lib/bad_encoding.rb +6 -0
- data/spec/dummy/spec/.gitkeep +0 -0
- data/spec/fixtures/20090630.yml +7922 -0
- data/spec/fixtures/coverage-153.rb +11 -0
- data/spec/fixtures/coverage.rb +13 -0
- data/spec/fixtures/exit0.sh +3 -0
- data/spec/fixtures/exit1.sh +3 -0
- data/spec/fixtures/hotspots/flog.yml +86 -0
- data/spec/fixtures/hotspots/generator.yml +47 -0
- data/spec/fixtures/hotspots/generator_analysis.yml +53 -0
- data/spec/fixtures/hotspots/reek.yml +14 -0
- data/spec/fixtures/hotspots/roodi.yml +13 -0
- data/spec/fixtures/hotspots/saikuro.yml +27 -0
- data/spec/fixtures/hotspots/several_metrics.yml +47 -0
- data/spec/fixtures/hotspots/stats.yml +4 -0
- data/spec/fixtures/hotspots/three_metrics_on_same_file.yml +36 -0
- data/spec/fixtures/line_numbers/foo.rb +33 -0
- data/spec/fixtures/line_numbers/module.rb +11 -0
- data/spec/fixtures/line_numbers/module_surrounds_class.rb +15 -0
- data/spec/fixtures/line_numbers/two_classes.rb +11 -0
- data/spec/fixtures/metric_missing.yml +1 -0
- data/spec/fixtures/rcov_output.txt +135 -0
- data/spec/fixtures/saikuro/app/controllers/sessions_controller.rb_cyclo.html +10 -0
- data/spec/fixtures/saikuro/app/controllers/users_controller.rb_cyclo.html +16 -0
- data/spec/fixtures/saikuro/index_cyclo.html +155 -0
- data/spec/fixtures/saikuro_sfiles/thing.rb_cyclo.html +11 -0
- data/spec/metric_fu/calculate_spec.rb +21 -0
- data/spec/metric_fu/configuration_spec.rb +90 -0
- data/spec/metric_fu/data_structures/line_numbers_spec.rb +63 -0
- data/spec/metric_fu/data_structures/location_spec.rb +110 -0
- data/spec/metric_fu/formatter/configuration_spec.rb +44 -0
- data/spec/metric_fu/formatter/html_spec.rb +138 -0
- data/spec/metric_fu/formatter/yaml_spec.rb +61 -0
- data/spec/metric_fu/formatter_spec.rb +49 -0
- data/spec/metric_fu/gem_version_spec.rb +12 -0
- data/spec/metric_fu/generator_spec.rb +130 -0
- data/spec/metric_fu/loader_spec.rb +10 -0
- data/spec/metric_fu/metric_spec.rb +46 -0
- data/spec/metric_fu/metrics/cane/configuration_spec.rb +22 -0
- data/spec/metric_fu/metrics/cane/generator_spec.rb +184 -0
- data/spec/metric_fu/metrics/churn/configuration_spec.rb +13 -0
- data/spec/metric_fu/metrics/churn/generator_spec.rb +64 -0
- data/spec/metric_fu/metrics/flay/configuration_spec.rb +13 -0
- data/spec/metric_fu/metrics/flay/generator_spec.rb +105 -0
- data/spec/metric_fu/metrics/flay/grapher_spec.rb +57 -0
- data/spec/metric_fu/metrics/flog/configuration_spec.rb +18 -0
- data/spec/metric_fu/metrics/flog/generator_spec.rb +77 -0
- data/spec/metric_fu/metrics/flog/grapher_spec.rb +107 -0
- data/spec/metric_fu/metrics/hotspots/analysis/analyzed_problems_spec.rb +104 -0
- data/spec/metric_fu/metrics/hotspots/analysis/analyzer_tables_spec.rb +71 -0
- data/spec/metric_fu/metrics/hotspots/analysis/ranking_spec.rb +30 -0
- data/spec/metric_fu/metrics/hotspots/analysis/rankings_spec.rb +97 -0
- data/spec/metric_fu/metrics/hotspots/analysis/table_spec.rb +6 -0
- data/spec/metric_fu/metrics/hotspots/generator_spec.rb +46 -0
- data/spec/metric_fu/metrics/hotspots/hotspot_analyzer_spec.rb +10 -0
- data/spec/metric_fu/metrics/hotspots/hotspot_spec.rb +16 -0
- data/spec/metric_fu/metrics/rails_best_practices/configuration_spec.rb +55 -0
- data/spec/metric_fu/metrics/rails_best_practices/generator_spec.rb +33 -0
- data/spec/metric_fu/metrics/rails_best_practices/grapher_spec.rb +62 -0
- data/spec/metric_fu/metrics/rcov/configuration_spec.rb +28 -0
- data/spec/metric_fu/metrics/rcov/generator_spec.rb +22 -0
- data/spec/metric_fu/metrics/rcov/grapher_spec.rb +57 -0
- data/spec/metric_fu/metrics/rcov/hotspot_spec.rb +20 -0
- data/spec/metric_fu/metrics/rcov/rcov_line_spec.rb +89 -0
- data/spec/metric_fu/metrics/rcov/simplecov_formatter_spec.rb +67 -0
- data/spec/metric_fu/metrics/reek/configuration_spec.rb +13 -0
- data/spec/metric_fu/metrics/reek/generator_spec.rb +169 -0
- data/spec/metric_fu/metrics/reek/grapher_spec.rb +66 -0
- data/spec/metric_fu/metrics/roodi/configuration_spec.rb +14 -0
- data/spec/metric_fu/metrics/roodi/generator_spec.rb +82 -0
- data/spec/metric_fu/metrics/roodi/grapher_spec.rb +57 -0
- data/spec/metric_fu/metrics/saikuro/configuration_spec.rb +25 -0
- data/spec/metric_fu/metrics/saikuro/generator_spec.rb +71 -0
- data/spec/metric_fu/metrics/stats/generator_spec.rb +96 -0
- data/spec/metric_fu/metrics/stats/grapher_spec.rb +69 -0
- data/spec/metric_fu/reporter_spec.rb +41 -0
- data/spec/metric_fu/reporting/graphs/graph_spec.rb +44 -0
- data/spec/metric_fu/reporting/graphs/grapher_spec.rb +24 -0
- data/spec/metric_fu/reporting/result_spec.rb +50 -0
- data/spec/metric_fu/run_spec.rb +197 -0
- data/spec/metric_fu/templates/configuration_spec.rb +51 -0
- data/spec/metric_fu/templates/metrics_template_spec.rb +11 -0
- data/spec/metric_fu/templates/report_spec.rb +15 -0
- data/spec/metric_fu/templates/template_spec.rb +233 -0
- data/spec/metric_fu/utility_spec.rb +12 -0
- data/spec/metric_fu_spec.rb +33 -0
- data/spec/quality_spec.rb +114 -0
- data/spec/shared/configured.rb +45 -0
- data/spec/shared/test_coverage.rb +95 -0
- data/spec/spec_helper.rb +54 -0
- data/spec/support/deferred_garbaged_collection.rb +33 -0
- data/spec/support/helper_methods.rb +32 -0
- data/spec/support/matcher_create_file.rb +37 -0
- data/spec/support/matcher_create_files.rb +43 -0
- data/spec/support/suite.rb +26 -0
- data/spec/support/test_fixtures.rb +37 -0
- data/spec/support/timeout.rb +7 -0
- data/spec/support/usage_test.rb +150 -0
- data/spec/usage_test_spec.rb +93 -0
- metadata +757 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
createGraphElement("div");
|
|
2
|
+
|
|
3
|
+
if(document.getElementById('graph')) {
|
|
4
|
+
var chart = new Highcharts.Chart({
|
|
5
|
+
chart: {
|
|
6
|
+
animation: false,
|
|
7
|
+
renderTo: 'graph'
|
|
8
|
+
},
|
|
9
|
+
legend: {
|
|
10
|
+
align: 'center',
|
|
11
|
+
verticalAlign: 'top',
|
|
12
|
+
y: 25
|
|
13
|
+
},
|
|
14
|
+
plotOptions: {
|
|
15
|
+
line: {
|
|
16
|
+
animation: false,
|
|
17
|
+
lineWidth: 3,
|
|
18
|
+
marker: {
|
|
19
|
+
radius: 6
|
|
20
|
+
},
|
|
21
|
+
pointPlacement: 'on'
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
title: {
|
|
25
|
+
text: graph_title
|
|
26
|
+
},
|
|
27
|
+
xAxis: {
|
|
28
|
+
categories: graph_labels,
|
|
29
|
+
tickmarkPlacement: 'on'
|
|
30
|
+
},
|
|
31
|
+
yAxis: {
|
|
32
|
+
maxPadding: 0,
|
|
33
|
+
min: 0,
|
|
34
|
+
minPadding: 0
|
|
35
|
+
},
|
|
36
|
+
series: graph_series
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
JS={extend:function(a,b){b=b||{};for(var c in b){if(a[c]===b[c])continue;a[c]=b[c]}return a},makeFunction:function(){return function(){return this.initialize?(this.initialize.apply(this,arguments)||this):this}},makeBridge:function(a){var b=function(){};b.prototype=a.prototype;return new b},bind:function(){var a=JS.array(arguments),b=a.shift(),c=a.shift()||null;return function(){return b.apply(c,a.concat(JS.array(arguments)))}},callsSuper:function(a){return a.SUPER===undefined?a.SUPER=/\bcallSuper\b/.test(a.toString()):a.SUPER},mask:function(a){var b=a.toString().replace(/callSuper/g,'super');a.toString=function(){return b};return a},array:function(a){if(!a)return[];if(a.toArray)return a.toArray();var b=a.length,c=[];while(b--)c[b]=a[b];return c},indexOf:function(a,b){for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},isFn:function(a){return a instanceof Function},isType:function(a,b){if(!a||!b)return false;return(b instanceof Function&&a instanceof b)||(typeof b==='string'&&typeof a===b)||(a.isA&&a.isA(b))},ignore:function(a,b){return/^(include|extend)$/.test(a)&&typeof b==='object'}};JS.Module=JS.makeFunction();JS.extend(JS.Module.prototype,{END_WITHOUT_DOT:/([^\.])$/,initialize:function(a,b,c){this.__mod__=this;this.__inc__=[];this.__fns__={};this.__dep__=[];this.__mct__={};if(typeof a==='string'){this.__nom__=this.displayName=a}else{this.__nom__=this.displayName='';c=b;b=a}c=c||{};this.__res__=c._1||null;if(b)this.include(b,false);if(JS.Module.__chainq__)JS.Module.__chainq__.push(this)},setName:function(a){this.__nom__=this.displayName=a||'';for(var b in this.__mod__.__fns__)this.__name__(b);if(a&&this.__meta__)this.__meta__.setName(a+'.')},__name__:function(a){if(!this.__nom__)return;var b=this.__mod__.__fns__[a]||{};a=this.__nom__.replace(this.END_WITHOUT_DOT,'$1#')+a;if(JS.isFn(b.setName))return b.setName(a);if(JS.isFn(b))b.displayName=a},define:function(a,b,c,d){var f=(d||{})._0||this;this.__fns__[a]=b;this.__name__(a);if(JS.Module._0&&f&&JS.isFn(b))JS.Module._0(a,f);if(c!==false)this.resolve()},instanceMethod:function(a){var b=this.lookup(a).pop();return JS.isFn(b)?b:null},instanceMethods:function(a,b){var c=this.__mod__,b=b||[],d=c.ancestors(),f=d.length,e;for(e in c.__fns__){if(c.__fns__.hasOwnProperty(e)&&JS.isFn(c.__fns__[e])&&JS.indexOf(b,e)===-1)b.push(e)}if(a===false)return b;while(f--)d[f].instanceMethods(false,b);return b},include:function(a,b,c){b=(b!==false);if(!a)return b?this.resolve():this.uncache();c=c||{};if(a.__mod__)a=a.__mod__;var d=a.include,f=a.extend,e=c._4||this,g,h,i,j;if(a.__inc__&&a.__fns__){this.__inc__.push(a);a.__dep__.push(this);if(c._2)a.extended&&a.extended(c._2);else a.included&&a.included(e)}else{if(c._5){for(h in a){if(JS.ignore(h,a[h]))continue;this.define(h,a[h],false,{_0:e||c._2||this})}}else{if(typeof d==='object'||JS.isType(d,JS.Module)){g=[].concat(d);for(i=0,j=g.length;i<j;i++)e.include(g[i],b,c)}if(typeof f==='object'||JS.isType(f,JS.Module)){g=[].concat(f);for(i=0,j=g.length;i<j;i++)e.extend(g[i],false);e.extend()}c._5=true;return e.include(a,b,c)}}b?this.resolve():this.uncache()},includes:function(a){var b=this.__mod__,c=b.__inc__.length;if(Object===a||b===a||b.__res__===a.prototype)return true;while(c--){if(b.__inc__[c].includes(a))return true}return false},match:function(a){return a.isA&&a.isA(this)},ancestors:function(a){var b=this.__mod__,c=(a===undefined),d=(b.__res__||{}).klass,f=(d&&b.__res__===d.prototype)?d:b,e,g;if(c&&b.__anc__)return b.__anc__.slice();a=a||[];for(e=0,g=b.__inc__.length;e<g;e++)b.__inc__[e].ancestors(a);if(JS.indexOf(a,f)===-1)a.push(f);if(c)b.__anc__=a.slice();return a},lookup:function(a){var b=this.__mod__,c=b.__mct__;if(c[a])return c[a].slice();var d=b.ancestors(),f=[],e,g,h;for(e=0,g=d.length;e<g;e++){h=d[e].__mod__.__fns__[a];if(h)f.push(h)}c[a]=f.slice();return f},make:function(a,b){if(!JS.isFn(b)||!JS.callsSuper(b))return b;var c=this;return function(){return c.chain(this,a,arguments)}},chain:JS.mask(function(c,d,f){var e=this.lookup(d),g=e.length-1,h=c.callSuper,i=JS.array(f),j;c.callSuper=function(){var a=arguments.length;while(a--)i[a]=arguments[a];g-=1;var b=e[g].apply(c,i);g+=1;return b};j=e.pop().apply(c,i);h?c.callSuper=h:delete c.callSuper;return j}),resolve:function(a){var b=this.__mod__,a=a||b,c=a.__res__,d,f,e,g;if(a===b){b.uncache(false);d=b.__dep__.length;while(d--)b.__dep__[d].resolve()}if(!c)return;for(d=0,f=b.__inc__.length;d<f;d++)b.__inc__[d].resolve(a);for(e in b.__fns__){g=a.make(e,b.__fns__[e]);if(c[e]!==g)c[e]=g}},uncache:function(a){var b=this.__mod__,c=b.__dep__.length;b.__anc__=null;b.__mct__={};if(a===false)return;while(c--)b.__dep__[c].uncache()}});JS.Class=JS.makeFunction();JS.extend(JS.Class.prototype=JS.makeBridge(JS.Module),{initialize:function(a,b,c){if(typeof a==='string'){this.__nom__=this.displayName=a}else{this.__nom__=this.displayName='';c=b;b=a}var d=JS.extend(JS.makeFunction(),this);d.klass=d.constructor=this.klass;if(!JS.isFn(b)){c=b;b=Object}d.inherit(b);d.include(c,false);d.resolve();do{b.inherited&&b.inherited(d)}while(b=b.superclass);return d},inherit:function(a){this.superclass=a;if(this.__eigen__&&a.__eigen__)this.extend(a.__eigen__(),true);this.subclasses=[];(a.subclasses||[]).push(this);var b=this.prototype=JS.makeBridge(a);b.klass=b.constructor=this;this.__mod__=new JS.Module(this.__nom__,{},{_1:this.prototype});this.include(JS.Kernel,false);if(a!==Object)this.include(a.__mod__||new JS.Module(a.prototype,{_1:a.prototype}),false)},include:function(a,b,c){if(!a)return;var d=this.__mod__,c=c||{};c._4=this;return d.include(a,b,c)},define:function(a,b,c,d){var f=this.__mod__;d=d||{};d._0=this;f.define(a,b,c,d)}});JS.Module=new JS.Class('Module',JS.Module.prototype);JS.Class=new JS.Class('Class',JS.Module,JS.Class.prototype);JS.Module.klass=JS.Module.constructor=JS.Class.klass=JS.Class.constructor=JS.Class;JS.extend(JS.Module,{_3:[],__chainq__:[],methodAdded:function(a,b){this._3.push([a,b])},_0:function(a,b){var c=this._3,d=c.length;while(d--)c[d][0].call(c[d][1]||null,a,b)}});JS.Kernel=JS.extend(new JS.Module('Kernel',{__eigen__:function(){if(this.__meta__)return this.__meta__;var a=this.__nom__,b=this.klass.__nom__,c=a||(b?'#<'+b+'>':''),d=this.__meta__=new JS.Module(c?c+'.':'',{},{_1:this});d.include(this.klass.__mod__,false);return d},equals:function(a){return this===a},extend:function(a,b){return this.__eigen__().include(a,b,{_2:this})},hash:function(){return this.__hashcode__=this.__hashcode__||JS.Kernel.getHashCode()},isA:function(a){return this.__eigen__().includes(a)},method:function(a){var b=this,c=b.__mcache__=b.__mcache__||{};if((c[a]||{}).fn===b[a])return c[a].bd;return(c[a]={fn:b[a],bd:JS.bind(b[a],b)}).bd},methods:function(){return this.__eigen__().instanceMethods(true)},tap:function(a,b){a.call(b||null,this);return this}}),{__hashIndex__:0,getHashCode:function(){this.__hashIndex__+=1;return(Math.floor(new Date().getTime()/1000)+this.__hashIndex__).toString(16)}});JS.Module.include(JS.Kernel);JS.extend(JS.Module,JS.Kernel.__fns__);JS.Class.include(JS.Kernel);JS.extend(JS.Class,JS.Kernel.__fns__);JS.Interface=new JS.Class({initialize:function(d){this.test=function(a,b){var c=d.length;while(c--){if(!JS.isFn(a[d[c]]))return b?d[c]:false}return true}},extend:{ensure:function(){var a=JS.array(arguments),b=a.shift(),c,d;while(c=a.shift()){d=c.test(b,true);if(d!==true)throw new Error('object does not implement '+d+'()');}}}});JS.Singleton=new JS.Class({initialize:function(a,b,c){return new(new JS.Class(a,b,c))}});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Highcharts JS v3.0.9 (2014-01-15)
|
|
3
|
+
|
|
4
|
+
Standalone Highcharts Framework
|
|
5
|
+
|
|
6
|
+
License: MIT License
|
|
7
|
+
*/
|
|
8
|
+
var HighchartsAdapter=function(){function o(c){function b(b,a,d){b.removeEventListener(a,d,!1)}function d(b,a,d){d=b.HCProxiedMethods[d.toString()];b.detachEvent("on"+a,d)}function a(a,c){var f=a.HCEvents,i,g,k,j;if(a.removeEventListener)i=b;else if(a.attachEvent)i=d;else return;c?(g={},g[c]=!0):g=f;for(j in g)if(f[j])for(k=f[j].length;k--;)i(a,j,f[j][k])}c.HCExtended||Highcharts.extend(c,{HCExtended:!0,HCEvents:{},bind:function(a,b){var d=this,c=this.HCEvents,g;if(d.addEventListener)d.addEventListener(a,
|
|
9
|
+
b,!1);else if(d.attachEvent){g=function(a){b.call(d,a)};if(!d.HCProxiedMethods)d.HCProxiedMethods={};d.HCProxiedMethods[b.toString()]=g;d.attachEvent("on"+a,g)}c[a]===r&&(c[a]=[]);c[a].push(b)},unbind:function(c,h){var f,i;c?(f=this.HCEvents[c]||[],h?(i=HighchartsAdapter.inArray(h,f),i>-1&&(f.splice(i,1),this.HCEvents[c]=f),this.removeEventListener?b(this,c,h):this.attachEvent&&d(this,c,h)):(a(this,c),this.HCEvents[c]=[])):(a(this),this.HCEvents={})},trigger:function(a,b){var d=this.HCEvents[a]||
|
|
10
|
+
[],c=d.length,g,k,j;k=function(){b.defaultPrevented=!0};for(g=0;g<c;g++){j=d[g];if(b.stopped)break;b.preventDefault=k;b.target=this;if(!b.type)b.type=a;j.call(this,b)===!1&&b.preventDefault()}}});return c}var r,l=document,p=[],m=[],q,n;Math.easeInOutSine=function(c,b,d,a){return-d/2*(Math.cos(Math.PI*c/a)-1)+b};return{init:function(c){if(!l.defaultView)this._getStyle=function(b,d){var a;return b.style[d]?b.style[d]:(d==="opacity"&&(d="filter"),a=b.currentStyle[d.replace(/\-(\w)/g,function(b,a){return a.toUpperCase()})],
|
|
11
|
+
d==="filter"&&(a=a.replace(/alpha\(opacity=([0-9]+)\)/,function(b,a){return a/100})),a===""?1:a)},this.adapterRun=function(b,d){var a={width:"clientWidth",height:"clientHeight"}[d];if(a)return b.style.zoom=1,b[a]-2*parseInt(HighchartsAdapter._getStyle(b,"padding"),10)};if(!Array.prototype.forEach)this.each=function(b,d){for(var a=0,c=b.length;a<c;a++)if(d.call(b[a],b[a],a,b)===!1)return a};if(!Array.prototype.indexOf)this.inArray=function(b,d){var a,c=0;if(d)for(a=d.length;c<a;c++)if(d[c]===b)return c;
|
|
12
|
+
return-1};if(!Array.prototype.filter)this.grep=function(b,d){for(var a=[],c=0,h=b.length;c<h;c++)d(b[c],c)&&a.push(b[c]);return a};n=function(b,c,a){this.options=c;this.elem=b;this.prop=a};n.prototype={update:function(){var b;b=this.paths;var d=this.elem,a=d.element;b&&a?d.attr("d",c.step(b[0],b[1],this.now,this.toD)):d.attr?a&&d.attr(this.prop,this.now):(b={},b[d]=this.now+this.unit,Highcharts.css(d,b));this.options.step&&this.options.step.call(this.elem,this.now,this)},custom:function(b,c,a){var e=
|
|
13
|
+
this,h=function(a){return e.step(a)},f;this.startTime=+new Date;this.start=b;this.end=c;this.unit=a;this.now=this.start;this.pos=this.state=0;h.elem=this.elem;h()&&m.push(h)===1&&(q=setInterval(function(){for(f=0;f<m.length;f++)m[f]()||m.splice(f--,1);m.length||clearInterval(q)},13))},step:function(b){var c=+new Date,a;a=this.options;var e;if(this.elem.stopAnimation)a=!1;else if(b||c>=a.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();b=this.options.curAnim[this.prop]=
|
|
14
|
+
!0;for(e in a.curAnim)a.curAnim[e]!==!0&&(b=!1);b&&a.complete&&a.complete.call(this.elem);a=!1}else e=c-this.startTime,this.state=e/a.duration,this.pos=a.easing(e,0,1,a.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update(),a=!0;return a}};this.animate=function(b,d,a){var e,h="",f,i,g;b.stopAnimation=!1;if(typeof a!=="object"||a===null)e=arguments,a={duration:e[2],easing:e[3],complete:e[4]};if(typeof a.duration!=="number")a.duration=400;a.easing=Math[a.easing]||Math.easeInOutSine;
|
|
15
|
+
a.curAnim=Highcharts.extend({},d);for(g in d)i=new n(b,a,g),f=null,g==="d"?(i.paths=c.init(b,b.d,d.d),i.toD=d.d,e=0,f=1):b.attr?e=b.attr(g):(e=parseFloat(HighchartsAdapter._getStyle(b,g))||0,g!=="opacity"&&(h="px")),f||(f=parseFloat(d[g])),i.custom(e,f,h)}},_getStyle:function(c,b){return window.getComputedStyle(c).getPropertyValue(b)},getScript:function(c,b){var d=l.getElementsByTagName("head")[0],a=l.createElement("script");a.type="text/javascript";a.src=c;a.onload=b;d.appendChild(a)},inArray:function(c,
|
|
16
|
+
b){return b.indexOf?b.indexOf(c):p.indexOf.call(b,c)},adapterRun:function(c,b){return parseInt(HighchartsAdapter._getStyle(c,b),10)},grep:function(c,b){return p.filter.call(c,b)},map:function(c,b){for(var d=[],a=0,e=c.length;a<e;a++)d[a]=b.call(c[a],c[a],a,c);return d},offset:function(c){for(var b=0,d=0;c;)b+=c.offsetLeft,d+=c.offsetTop,c=c.offsetParent;return{left:b,top:d}},addEvent:function(c,b,d){o(c).bind(b,d)},removeEvent:function(c,b,d){o(c).unbind(b,d)},fireEvent:function(c,b,d,a){var e;l.createEvent&&
|
|
17
|
+
(c.dispatchEvent||c.fireEvent)?(e=l.createEvent("Events"),e.initEvent(b,!0,!0),e.target=c,Highcharts.extend(e,d),c.dispatchEvent?c.dispatchEvent(e):c.fireEvent(b,e)):c.HCExtended===!0&&(d=d||{},c.trigger(b,d));d&&d.defaultPrevented&&(a=null);a&&a(d)},washMouseEvent:function(c){return c},stop:function(c){c.stopAnimation=!0},each:function(c,b){return Array.prototype.forEach.call(c,b)}}}();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
function createGraphElement(elementType) {
|
|
2
|
+
var graphContainer = document.getElementById("graph_container");
|
|
3
|
+
|
|
4
|
+
if(graphContainer) {
|
|
5
|
+
var graphElement = document.createElement(elementType);
|
|
6
|
+
graphElement.setAttribute("id", "graph");
|
|
7
|
+
graphContainer.appendChild(graphElement);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
2
|
+
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
|
|
3
|
+
<head>
|
|
4
|
+
<meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
|
|
5
|
+
<meta content='en' http-equiv='Content-Language' />
|
|
6
|
+
<title>metrics</title>
|
|
7
|
+
<style>
|
|
8
|
+
<%= inline_css("css/reset.css") %>
|
|
9
|
+
<%= inline_css("css/buttons.css") %>
|
|
10
|
+
<%= inline_css("css/integrity.css") %>
|
|
11
|
+
<%= inline_css("css/default.css") %>
|
|
12
|
+
<%= inline_css("css/bluff.css") %>
|
|
13
|
+
</style>
|
|
14
|
+
<link REL="SHORTCUT ICON" HREF="/favicon.ico">
|
|
15
|
+
<% if not @disable_js %>
|
|
16
|
+
<script language="javascript" src="../javascripts/utils.js" type="text/javascript"></script>
|
|
17
|
+
<script language="javascript" src="../javascripts/js-class.js" type="text/javascript"></script>
|
|
18
|
+
<script language="javascript" src="../javascripts/bluff-min.js" type="text/javascript"></script>
|
|
19
|
+
<script language="javascript" src="../javascripts/excanvas.js" type="text/javascript"></script>
|
|
20
|
+
<script language="javascript" src="../javascripts/standalone-framework.js" type="text/javascript"></script>
|
|
21
|
+
<script language="javascript" src="../javascripts/highcharts.js" type="text/javascript"></script>
|
|
22
|
+
<% end %>
|
|
23
|
+
</head>
|
|
24
|
+
<body>
|
|
25
|
+
<div id='header'>
|
|
26
|
+
<h1><a href="/">metrics</a> | <a href="index.html"><%= @name %></a></h1>
|
|
27
|
+
<address class='watermark'>
|
|
28
|
+
built with
|
|
29
|
+
<a href='<%= MetricFu.metric_url %>'><%= MetricFu.metric_name %></a>
|
|
30
|
+
</address>
|
|
31
|
+
</div>
|
|
32
|
+
<div id='content'>
|
|
33
|
+
<%= @html %>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<% if not @disable_js %>
|
|
37
|
+
<% graph_engine = MetricFu.configuration.graph_engine.to_s %>
|
|
38
|
+
<script language="javascript" src="../javascripts/<%= graph_engine %>_graph.js" type="text/javascript"></script>
|
|
39
|
+
<% end %>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
MetricFu.lib_require { "templates/template" }
|
|
3
|
+
MetricFu.lib_require { "templates/report" }
|
|
4
|
+
|
|
5
|
+
# The MetricsTemplate class is the included template used by the HTML formatter.
|
|
6
|
+
# The only requirement for a template class is that it provides a #write method
|
|
7
|
+
# to actually write out the template.
|
|
8
|
+
module MetricFu
|
|
9
|
+
class Templates::MetricsTemplate < MetricFu::Template
|
|
10
|
+
attr_accessor :result, :per_file_data, :formatter, :metrics, :name, :html
|
|
11
|
+
|
|
12
|
+
def write
|
|
13
|
+
self.name = MetricFu.report_name
|
|
14
|
+
self.metrics = {}
|
|
15
|
+
|
|
16
|
+
copy_javascripts
|
|
17
|
+
|
|
18
|
+
result.each_pair do |section, contents|
|
|
19
|
+
write_section(section, contents)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
write_index
|
|
23
|
+
write_file_data
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def html_filename(file)
|
|
27
|
+
file = Digest::SHA1.hexdigest(file)[0..29]
|
|
28
|
+
"#{file.gsub(%r{/}, '_')}.html"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def copy_javascripts
|
|
34
|
+
FileUtils.mkdir_p(File.join(output_directory, "javascripts"))
|
|
35
|
+
Dir[File.join(template_directory, "javascripts", "*")].each do |f|
|
|
36
|
+
FileUtils.cp(f, File.join(output_directory, "javascripts", File.basename(f)))
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def write_section(section, contents)
|
|
41
|
+
if template_exists?(section)
|
|
42
|
+
create_instance_var(section, contents)
|
|
43
|
+
metrics[section] = contents
|
|
44
|
+
create_instance_var(:per_file_data, per_file_data)
|
|
45
|
+
mf_debug "Generating html for section #{section} with #{template(section)} for result #{result.class}"
|
|
46
|
+
self.html = erbify(section)
|
|
47
|
+
layout = erbify("layout")
|
|
48
|
+
dir = "results"
|
|
49
|
+
FileUtils.mkdir_p(File.join(output_directory, dir))
|
|
50
|
+
fn = output_filename(section)
|
|
51
|
+
formatter.write_template(layout, "#{dir}/#{fn}")
|
|
52
|
+
else
|
|
53
|
+
mf_debug "no template for section #{section} with #{template(section)} for result #{result.class}"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def write_index
|
|
58
|
+
# Instance variables we need should already be created from above
|
|
59
|
+
if template_exists?("index")
|
|
60
|
+
self.html = erbify("index")
|
|
61
|
+
layout = erbify("layout")
|
|
62
|
+
fn = output_filename("index")
|
|
63
|
+
formatter.write_template(layout, fn)
|
|
64
|
+
else
|
|
65
|
+
mf_debug "no template for section index for result #{result.class}"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def write_file_data
|
|
70
|
+
per_file_data.each_pair do |file, lines|
|
|
71
|
+
next if file.to_s.empty?
|
|
72
|
+
next unless File.file?(file)
|
|
73
|
+
report = MetricFu::Templates::Report.new(file, lines).render
|
|
74
|
+
|
|
75
|
+
dir = "codes/" + File.dirname(file)
|
|
76
|
+
FileUtils.mkdir_p(File.join(output_directory, dir))
|
|
77
|
+
fn = File.basename(file) + ".html"
|
|
78
|
+
formatter.write_template(report, "#{dir}/#{fn}")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def template_directory
|
|
83
|
+
File.dirname(__FILE__)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<style>
|
|
4
|
+
<%= inline_css('css/syntax.css') %>
|
|
5
|
+
</style>
|
|
6
|
+
<title>Analyzed File Report</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<table cellpadding='0' cellspacing='0' class='ruby'>
|
|
10
|
+
<% @data.each_with_index do |line, idx| %>
|
|
11
|
+
<% line_number = (idx + 1).to_s %>
|
|
12
|
+
<tr>
|
|
13
|
+
<td valign='top'>
|
|
14
|
+
<% if @lines.has_key?(line_number) %>
|
|
15
|
+
<ul>
|
|
16
|
+
<% @lines[line_number].each do |problem| %>
|
|
17
|
+
<li><%= "#{problem[:description]} » #{problem[:type]}" %></li>
|
|
18
|
+
<% end %>
|
|
19
|
+
</ul>
|
|
20
|
+
<% else %>
|
|
21
|
+
|
|
22
|
+
<% end %>
|
|
23
|
+
</td>
|
|
24
|
+
<td valign='top'>
|
|
25
|
+
<%= line_for_display(line, line_number) %>
|
|
26
|
+
</td>
|
|
27
|
+
</tr>
|
|
28
|
+
<% end %>
|
|
29
|
+
</table>
|
|
30
|
+
</body>
|
|
31
|
+
</html>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
MetricFu.lib_require { "formatter/syntax" }
|
|
2
|
+
MetricFu.lib_require { "templates/template" }
|
|
3
|
+
|
|
4
|
+
# Creates an HTML document for a given analyzed file,
|
|
5
|
+
# with scored metrics annotating the relevant line.
|
|
6
|
+
module MetricFu
|
|
7
|
+
module Templates
|
|
8
|
+
class Report < MetricFu::Template
|
|
9
|
+
# @param file [String] the analyzed file to annotate
|
|
10
|
+
# @param lines [Hash] of line number [String] keyed to an list [[Array] of metrics for that line. Each metric in the list is a hash containing the keys :type => metric_name, :descrption => metric_score
|
|
11
|
+
# @example file and lines
|
|
12
|
+
# file: "lib/metric_fu/gem_version.rb
|
|
13
|
+
# lines: {"30"=>[{:type=>:flog, :description=>"Score of 22.43"}], "42"=>[{:type=>:flog, :description=>"Score of 8.64"}]}
|
|
14
|
+
def initialize(file, lines)
|
|
15
|
+
@file = file
|
|
16
|
+
@lines = lines
|
|
17
|
+
@data = File.open(file, "rb") { |f| f.readlines }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def render
|
|
21
|
+
erbify("report")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def convert_ruby_to_html(ruby_text, line_number)
|
|
25
|
+
MetricFu::Formatter::Syntax.new.highlight(ruby_text, line_number)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def line_for_display(line, line_number)
|
|
29
|
+
if MetricFu::Formatter::Templates.option("syntax_highlighting")
|
|
30
|
+
line_for_display = convert_ruby_to_html(line, line_number)
|
|
31
|
+
else
|
|
32
|
+
"<a name='n#{line_number}' href='n#{line_number}'>#{line_number}</a>#{line}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def template_directory
|
|
37
|
+
File.dirname(__FILE__)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
require "erb"
|
|
2
|
+
module MetricFu
|
|
3
|
+
class Template
|
|
4
|
+
attr_accessor :output_directory
|
|
5
|
+
|
|
6
|
+
def output_directory
|
|
7
|
+
@output_directory || MetricFu::Io::FileSystem.directory("output_directory")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Renders a partial and add optional instance variables to the template
|
|
11
|
+
# @param name <String> name of partial, omitting leading underscore (_)
|
|
12
|
+
# @param instance_variables <Hash> of instance variable
|
|
13
|
+
# names and values to set
|
|
14
|
+
def render_partial(name, instance_variables = {})
|
|
15
|
+
create_instance_vars(instance_variables)
|
|
16
|
+
erbify("_#{name}")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
# Creates a new erb evaluated result from the passed in section.
|
|
22
|
+
#
|
|
23
|
+
# @param section String
|
|
24
|
+
# The section name of
|
|
25
|
+
#
|
|
26
|
+
# @return String
|
|
27
|
+
# The erb evaluated string
|
|
28
|
+
def erbify(section)
|
|
29
|
+
template_file = template(section)
|
|
30
|
+
erb = erb_template_source(template_file)
|
|
31
|
+
erb.result(binding)
|
|
32
|
+
rescue => e
|
|
33
|
+
message = "Error: #{e.class}; message #{e.message}. "
|
|
34
|
+
message << "Failed evaluating erb template "
|
|
35
|
+
message << "for section #{section} and template #{template_file}."
|
|
36
|
+
raise message
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def erb_template_source(template_file)
|
|
40
|
+
erb_doc = File.read(template_file)
|
|
41
|
+
erb = ERB.new(erb_doc)
|
|
42
|
+
erb.filename = template_file
|
|
43
|
+
erb
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Copies an instance variable mimicing the name of the section
|
|
47
|
+
# we are trying to render, with a value equal to the passed in
|
|
48
|
+
# constant. Allows the concrete template classes to refer to
|
|
49
|
+
# that instance variable from their ERB rendering
|
|
50
|
+
#
|
|
51
|
+
# @param section String
|
|
52
|
+
# The name of the instance variable to create
|
|
53
|
+
#
|
|
54
|
+
# @param contents Object
|
|
55
|
+
# The value to set as the value of the created instance
|
|
56
|
+
# variable
|
|
57
|
+
def create_instance_var(section, contents)
|
|
58
|
+
instance_variable_set("@#{section}", contents)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def create_instance_vars(variables)
|
|
62
|
+
variables.each { |variable| create_instance_var(*variable) }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Generates the filename of the template file to load and
|
|
66
|
+
# evaluate. In this case, the path to the template directory +
|
|
67
|
+
# the section name + .html.erb
|
|
68
|
+
#
|
|
69
|
+
# @param section String
|
|
70
|
+
# A section of the template to render
|
|
71
|
+
#
|
|
72
|
+
# @return String
|
|
73
|
+
# A file path
|
|
74
|
+
def template(section)
|
|
75
|
+
# TODO: each MetricFu::Metric should know about its templates
|
|
76
|
+
# This class knows too much about the filesystem structure
|
|
77
|
+
if MetricFu::Metric.enabled_metrics.map(&:name).include?(section) # expects a symbol
|
|
78
|
+
metric_template_path(section.to_s)
|
|
79
|
+
else
|
|
80
|
+
File.join(template_directory, section.to_s + ".html.erb")
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def metric_template_path(metric)
|
|
85
|
+
File.join(MetricFu.metrics_dir, metric, "report.html.erb")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Determines whether a template file exists for a given section
|
|
89
|
+
# of the full template.
|
|
90
|
+
#
|
|
91
|
+
# @param section String
|
|
92
|
+
# The section of the template to check against
|
|
93
|
+
#
|
|
94
|
+
# @return Boolean
|
|
95
|
+
# Does a template file exist for this section or not?
|
|
96
|
+
def template_exists?(section)
|
|
97
|
+
File.exist?(template(section))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Returns the filename that the template will render into for
|
|
101
|
+
# a given section. In this case, the section name + '.html'
|
|
102
|
+
#
|
|
103
|
+
# @param section String
|
|
104
|
+
# A section of the template to render
|
|
105
|
+
#
|
|
106
|
+
# @return String
|
|
107
|
+
# The output filename
|
|
108
|
+
def output_filename(section)
|
|
109
|
+
section.to_s + ".html"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns the contents of a given css file in order to
|
|
113
|
+
# render it inline into a template.
|
|
114
|
+
#
|
|
115
|
+
# @param css String
|
|
116
|
+
# The name of a css file to open
|
|
117
|
+
#
|
|
118
|
+
# @return String
|
|
119
|
+
# The contents of the css file
|
|
120
|
+
def inline_css(css)
|
|
121
|
+
css_file = File.join(MetricFu.lib_dir, "templates", css)
|
|
122
|
+
MetricFu::Utility.binread(css_file)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Provides a link to open a file through the textmate protocol
|
|
126
|
+
# on Darwin, or otherwise, a simple file link.
|
|
127
|
+
#
|
|
128
|
+
# @param name String
|
|
129
|
+
#
|
|
130
|
+
# @param line Integer
|
|
131
|
+
# The line number to link to, if textmate is available. Defaults
|
|
132
|
+
# to nil
|
|
133
|
+
#
|
|
134
|
+
# @return String
|
|
135
|
+
# An anchor link to a textmate reference or a file reference
|
|
136
|
+
def link_to_filename(name, line = nil, link_content = nil)
|
|
137
|
+
# href = file_url(name, line)
|
|
138
|
+
href = "../codes/#{name}.html"
|
|
139
|
+
href += "#n#{line}" if line
|
|
140
|
+
link_text = link_content(name, line, link_content)
|
|
141
|
+
"<a href='#{href}'>#{link_text}</a>"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def round_to_tenths(decimal)
|
|
145
|
+
decimal = 0.0 if decimal.to_s.eql?("NaN")
|
|
146
|
+
(decimal * 10).round / 10.0
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def link_content(name, line = nil, link_content = nil) # :nodoc:
|
|
150
|
+
if link_content
|
|
151
|
+
link_content
|
|
152
|
+
elsif line
|
|
153
|
+
"#{name}:#{line}"
|
|
154
|
+
else
|
|
155
|
+
name
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def display_location(location)
|
|
160
|
+
class_name, method_name = location.fetch("class_name"), location.fetch("method_name")
|
|
161
|
+
str = ""
|
|
162
|
+
str += link_to_filename(location.fetch("file_name"), location.fetch("line_number"))
|
|
163
|
+
str += " : " if method_name || class_name
|
|
164
|
+
if method_name
|
|
165
|
+
str += "#{method_name}"
|
|
166
|
+
else
|
|
167
|
+
# TODO HOTSPOTS BUG ONLY exists on move over to metric_fu
|
|
168
|
+
if class_name.is_a?(String)
|
|
169
|
+
str += "#{class_name}"
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
str
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def file_url(name, line) # :nodoc:
|
|
176
|
+
return "" unless name
|
|
177
|
+
filename = complete_file_path(name)
|
|
178
|
+
|
|
179
|
+
if render_as_txmt_protocol?
|
|
180
|
+
"txmt://open/?url=file://#{filename}" << (line ? "&line=#{line}" : "")
|
|
181
|
+
else
|
|
182
|
+
link_prefix = MetricFu.configuration.templates_option("link_prefix")
|
|
183
|
+
if link_prefix == MetricFu::Templates::Configuration::FILE_PREFIX
|
|
184
|
+
path = filename
|
|
185
|
+
else
|
|
186
|
+
path = name.gsub(/:.*$/, "")
|
|
187
|
+
end
|
|
188
|
+
"#{link_prefix}/#{path}"
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def complete_file_path(filename)
|
|
193
|
+
File.expand_path(filename)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def render_as_txmt_protocol? # :nodoc:
|
|
197
|
+
if MetricFu.configuration.osx?
|
|
198
|
+
!MetricFu.configuration.templates_option("darwin_txmt_protocol_no_thanks")
|
|
199
|
+
else
|
|
200
|
+
false
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Provides a brain dead way to cycle between two values during
|
|
205
|
+
# an iteration of some sort. Pass in the first_value, the second_value,
|
|
206
|
+
# and the cardinality of the iteration.
|
|
207
|
+
#
|
|
208
|
+
# @param first_value Object
|
|
209
|
+
#
|
|
210
|
+
# @param second_value Object
|
|
211
|
+
#
|
|
212
|
+
# @param iteration Integer
|
|
213
|
+
# The number of times through the iteration.
|
|
214
|
+
#
|
|
215
|
+
# @return Object
|
|
216
|
+
# The first_value if iteration is even. The second_value if
|
|
217
|
+
# iteration is odd.
|
|
218
|
+
def cycle(first_value, second_value, iteration)
|
|
219
|
+
return first_value if iteration % 2 == 0
|
|
220
|
+
second_value
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# available in the erb template
|
|
224
|
+
# as it's processed in the context of
|
|
225
|
+
# the binding of this class
|
|
226
|
+
def metric_links
|
|
227
|
+
@metrics.keys.map { |metric| metric_link(metric.to_s) }
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def metric_link(metric)
|
|
231
|
+
metric_summary = Gem.loaded_specs[metric.to_s]&.summary
|
|
232
|
+
<<-LINK
|
|
233
|
+
<a href="results/#{metric}.html" title="#{metric_summary}">
|
|
234
|
+
#{snake_case_to_title_case(metric)}
|
|
235
|
+
</a>
|
|
236
|
+
LINK
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def snake_case_to_title_case(string)
|
|
240
|
+
string.split("_").collect { |word| word[0] = word[0..0].upcase; word }.join(" ")
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def template_directory
|
|
244
|
+
fail "subclasses must specify template_directory. Usually File.dirname(__FILE__)"
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require "yaml"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
module MetricFu
|
|
4
|
+
module Utility
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
ESCAPE_CODES_PATTERN = Regexp.new('\e\[(?:\d;)?\d{1,2}m')
|
|
8
|
+
|
|
9
|
+
# Removes non-ASCII characters
|
|
10
|
+
def clean_ascii_text(text)
|
|
11
|
+
if text.respond_to?(:encode)
|
|
12
|
+
# avoids invalid multi-byte escape error
|
|
13
|
+
ascii_text = text.encode("ASCII", invalid: :replace, undef: :replace, replace: "")
|
|
14
|
+
# see http://www.ruby-forum.com/topic/183413
|
|
15
|
+
pattern = Regexp.new('[\x80-\xff]', nil, "n")
|
|
16
|
+
ascii_text.gsub(pattern, "")
|
|
17
|
+
else
|
|
18
|
+
text
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def stringify_keys(hash)
|
|
23
|
+
result = {}
|
|
24
|
+
hash.each do |key, value|
|
|
25
|
+
result[key.to_s] = value
|
|
26
|
+
end
|
|
27
|
+
result
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def strip_escape_codes(text)
|
|
31
|
+
text.gsub(ESCAPE_CODES_PATTERN, "")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def rm_rf(*args)
|
|
35
|
+
FileUtils.rm_rf(*args)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def mkdir_p(*args)
|
|
39
|
+
FileUtils.mkdir_p(*args)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def glob(*args)
|
|
43
|
+
Dir.glob(*args)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def load_yaml(file)
|
|
47
|
+
YAML.load_file(file)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def binread(file)
|
|
51
|
+
File.binread(file)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# From episode 029 of Ruby Tapas by Avdi
|
|
55
|
+
# https://rubytapas.dpdcart.com/subscriber/post?id=88
|
|
56
|
+
def capture_output(stream = STDOUT, &_block)
|
|
57
|
+
old_stdout = stream.clone
|
|
58
|
+
pipe_r, pipe_w = IO.pipe
|
|
59
|
+
pipe_r.sync = true
|
|
60
|
+
output = ""
|
|
61
|
+
reader = Thread.new do
|
|
62
|
+
begin
|
|
63
|
+
loop do
|
|
64
|
+
output << pipe_r.readpartial(1024)
|
|
65
|
+
end
|
|
66
|
+
rescue EOFError
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
stream.reopen(pipe_w)
|
|
70
|
+
yield
|
|
71
|
+
ensure
|
|
72
|
+
stream.reopen(old_stdout)
|
|
73
|
+
pipe_w.close
|
|
74
|
+
reader.join
|
|
75
|
+
pipe_r.close
|
|
76
|
+
return output
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|