metric_fu 4.2.1 → 4.3.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.
- data/.metrics +19 -1
- data/.travis.yml +2 -2
- data/Gemfile +2 -1
- data/HISTORY.md +24 -0
- data/README.md +60 -1
- data/TODO.md +1 -0
- data/bin/mf-saikuro +8 -0
- data/checksum/metric_fu-4.3.0.gem.sha512 +1 -0
- data/gemfiles/Gemfile.travis +9 -0
- data/lib/metric_fu.rb +1 -1
- data/lib/metric_fu/cli/client.rb +2 -2
- data/lib/metric_fu/cli/helper.rb +3 -3
- data/lib/metric_fu/cli/parser.rb +37 -16
- data/lib/metric_fu/configuration.rb +9 -1
- data/lib/metric_fu/constantize.rb +57 -0
- data/lib/metric_fu/data_structures/line_numbers.rb +19 -3
- data/lib/metric_fu/data_structures/location.rb +8 -3
- data/lib/metric_fu/formatter.rb +24 -0
- data/lib/metric_fu/formatter/html.rb +91 -0
- data/lib/metric_fu/formatter/yaml.rb +18 -0
- data/lib/metric_fu/initial_requires.rb +0 -1
- data/lib/metric_fu/io.rb +69 -0
- data/lib/metric_fu/load_files.rb +5 -2
- data/lib/metric_fu/logging/mf_debugger.rb +23 -0
- data/lib/metric_fu/metrics/base_template.rb +10 -4
- data/lib/metric_fu/metrics/cane/cane.rb +2 -1
- data/lib/metric_fu/metrics/cane/cane_bluff_grapher.rb +10 -9
- data/lib/metric_fu/metrics/cane/cane_gchart_grapher.rb +25 -0
- data/lib/metric_fu/metrics/flay/flay_bluff_grapher.rb +10 -9
- data/lib/metric_fu/metrics/flay/flay_gchart_grapher.rb +14 -11
- data/lib/metric_fu/metrics/flog/flog_bluff_grapher.rb +11 -10
- data/lib/metric_fu/metrics/flog/flog_gchart_grapher.rb +22 -15
- data/lib/metric_fu/metrics/generator.rb +10 -10
- data/lib/metric_fu/metrics/graph.rb +2 -2
- data/lib/metric_fu/metrics/hotspots/analysis/scoring_strategies.rb +3 -3
- data/lib/metric_fu/metrics/hotspots/hotspot.rb +4 -3
- data/lib/metric_fu/metrics/hotspots/hotspot_analyzer.rb +19 -10
- data/lib/metric_fu/metrics/hotspots/hotspots.rb +1 -1
- data/lib/metric_fu/metrics/hotspots/template_awesome/hotspots.html.erb +45 -45
- data/lib/metric_fu/metrics/rails_best_practices/rails_best_practices_bluff_grapher.rb +10 -9
- data/lib/metric_fu/metrics/rails_best_practices/rails_best_practices_gchart_grapher.rb +21 -15
- data/lib/metric_fu/metrics/rcov/rcov.rb +1 -1
- data/lib/metric_fu/metrics/rcov/rcov_bluff_grapher.rb +10 -9
- data/lib/metric_fu/metrics/rcov/rcov_gchart_grapher.rb +13 -8
- data/lib/metric_fu/metrics/reek/reek_bluff_grapher.rb +9 -13
- data/lib/metric_fu/metrics/reek/reek_gchart_grapher.rb +22 -17
- data/lib/metric_fu/metrics/roodi/roodi_bluff_grapher.rb +10 -9
- data/lib/metric_fu/metrics/roodi/roodi_gchart_grapher.rb +14 -11
- data/lib/metric_fu/metrics/saikuro/saikuro.rb +5 -34
- data/lib/metric_fu/metrics/stats/stats.rb +2 -1
- data/lib/metric_fu/metrics/stats/stats_bluff_grapher.rb +11 -10
- data/lib/metric_fu/metrics/stats/stats_gchart_grapher.rb +21 -14
- data/lib/metric_fu/reporter.rb +37 -0
- data/lib/metric_fu/reporting/graphs/engines/bluff.rb +20 -0
- data/lib/metric_fu/reporting/graphs/engines/gchart.rb +41 -3
- data/lib/metric_fu/reporting/graphs/grapher.rb +9 -2
- data/lib/metric_fu/reporting/result.rb +51 -0
- data/lib/metric_fu/reporting/templates/awesome/awesome_template.rb +8 -8
- data/lib/metric_fu/run.rb +34 -39
- data/lib/metric_fu/version.rb +1 -1
- data/lib/metric_fu_requires.rb +50 -33
- data/metric_fu.gemspec +30 -39
- data/spec/cli/helper_spec.rb +15 -0
- data/spec/metric_fu/configuration_spec.rb +40 -2
- data/spec/metric_fu/formatter/html_spec.rb +134 -0
- data/spec/metric_fu/formatter/yaml_spec.rb +59 -0
- data/spec/metric_fu/formatter_spec.rb +49 -0
- data/spec/metric_fu/metrics/base_template_spec.rb +23 -23
- data/spec/metric_fu/metrics/cane/cane_spec.rb +2 -2
- data/spec/metric_fu/metrics/churn/churn_spec.rb +1 -1
- data/spec/metric_fu/metrics/flay/flay_spec.rb +4 -4
- data/spec/metric_fu/metrics/flog/flog_spec.rb +7 -7
- data/spec/metric_fu/metrics/generator_spec.rb +21 -21
- data/spec/metric_fu/metrics/graph_spec.rb +9 -9
- data/spec/metric_fu/metrics/hotspots/hotspots_spec.rb +1 -1
- data/spec/metric_fu/metrics/rcov/rcov_spec.rb +8 -8
- data/spec/metric_fu/metrics/reek/reek_spec.rb +1 -1
- data/spec/metric_fu/metrics/saikuro/saikuro_spec.rb +5 -5
- data/spec/metric_fu/metrics/stats/stats_spec.rb +4 -4
- data/spec/metric_fu/reporter_spec.rb +41 -0
- data/spec/metric_fu/reporting/graphs/engines/gchart_spec.rb +7 -7
- data/spec/metric_fu/reporting/result_spec.rb +51 -0
- data/spec/run_spec.rb +167 -27
- data/spec/spec_helper.rb +1 -0
- data/spec/support/matcher_create_file.rb +7 -2
- data/spec/support/matcher_create_files.rb +41 -0
- data/spec/support/suite.rb +32 -0
- metadata +27 -6
- data/lib/metric_fu/reporting/report.rb +0 -111
- data/spec/metric_fu/reporting/report_spec.rb +0 -148
data/.metrics
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
3
|
# For testing that this file gets loaded
|
|
4
|
-
|
|
4
|
+
$metric_file_loaded = true
|
|
5
|
+
|
|
5
6
|
# example configuration
|
|
6
7
|
# MetricFu::Configuration.run do |config|
|
|
7
8
|
# coverage_file = File.expand_path("coverage/rcov/rcov.txt", Dir.pwd)
|
|
@@ -16,3 +17,20 @@ mf_debug "Metrics config loaded"
|
|
|
16
17
|
# end
|
|
17
18
|
# you may enable running rcov manually with
|
|
18
19
|
# MetricFu.run_rcov
|
|
20
|
+
#
|
|
21
|
+
# By default, metric_fu will use the built-in html formatter
|
|
22
|
+
# to generate HTML reports for each metric with pretty graphs.
|
|
23
|
+
|
|
24
|
+
# To configure different formatter(s) or output ...
|
|
25
|
+
# MetricFu::Configuration.run do |config|
|
|
26
|
+
# config.add_formatter(:html)
|
|
27
|
+
# config.add_formatter(:yaml, "customreport.yml")
|
|
28
|
+
# config.add_formatter(MyCustomFormatter)
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# metric_fu will attempt to require a custom formatter by
|
|
32
|
+
# fully qualified name based on ruby search path,
|
|
33
|
+
# but you may find that you need to add a require above.
|
|
34
|
+
#
|
|
35
|
+
# For instance, to require a formatter in your app's lib directory:
|
|
36
|
+
# require './lib/my_custom_formatter.rb'
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/HISTORY.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
|
+
Changes are below categorized as `Features, Fixes, or Misc`.
|
|
2
|
+
|
|
3
|
+
Each change should fall into categories that would affect whether the release is major (breaking changes), minor (new behavior), or patch (bug fix). See [semver](http://semver.org/) and [pessimistic versioning](http://docs.rubygems.org/read/chapter/16#page74)
|
|
4
|
+
|
|
5
|
+
As such, a _Feature_ would map to either major or minor. A _bug fix_ to a patch. And _misc_ is either minor or patch, the difference being kind of fuzzy for the purposes of history. Adding tests would be patch level.
|
|
6
|
+
|
|
1
7
|
### Master
|
|
2
8
|
|
|
9
|
+
### MetricFu 4.3.0 / 2013-07-26
|
|
10
|
+
|
|
11
|
+
* Features
|
|
12
|
+
* Allow customization of reporting results using formatters (Robin Curry #94)
|
|
13
|
+
* Fixes
|
|
14
|
+
* obey --no-open option (Chris Mason)
|
|
15
|
+
* Don't run the hotspots metric if it has been disabled (Chris Mason)
|
|
16
|
+
* No longer crashes when rake stats outputs blank lines (Benjamin Fleischer #103, #24)
|
|
17
|
+
* Run saikuro metrics the same way as the other metrics (Martin Gotink #100)
|
|
18
|
+
* Add missing Cane Google Chart Grapher (Benjamin Fleischer)
|
|
19
|
+
* Fix wrong arguments to display_location, split off line numbers from paths (Benjamin Fleischer #88)
|
|
20
|
+
* Remove line numbers from direct file link so the browser can open it (Benjamin Fleischer #82)
|
|
21
|
+
* Make the run specs work without the need to shell out (Robin Curry)
|
|
22
|
+
* Misc
|
|
23
|
+
* metric_fu runs with the -r option by default (Chris Mason #69)
|
|
24
|
+
* Switch to metric_fu-Saikuro gem (Benjamin Fleischer)
|
|
25
|
+
* Reduce Grapher code duplication (Benjamin Fleischer #89)
|
|
26
|
+
|
|
3
27
|
### MetricFu 4.2.1 / 2013-05-23
|
|
4
28
|
|
|
5
29
|
* Fixes
|
data/README.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
# MetricFu [](http://badge.fury.io/rb/metric_fu) [](http://travis-ci.org/metricfu/metric_fu) [
|
|
1
|
+
# MetricFu [](http://badge.fury.io/rb/metric_fu) [](http://travis-ci.org/metricfu/metric_fu) [Rdoc](http://rdoc.info/github/metricfu/metric_fu/)
|
|
2
|
+
|
|
3
|
+
[](https://codeclimate.com/github/metricfu/metric_fu) [](https://gemnasium.com/metricfu/metric_fu)
|
|
2
4
|
|
|
3
5
|
## Metrics
|
|
4
6
|
|
|
@@ -47,6 +49,63 @@ See `metric_fu --help` for more options
|
|
|
47
49
|
|
|
48
50
|
* Cane code quality threshold checking is not included in the hotspots report
|
|
49
51
|
|
|
52
|
+
## Formatters
|
|
53
|
+
|
|
54
|
+
### Built-in Formatters
|
|
55
|
+
|
|
56
|
+
By default, metric_fu will use the built-in html formatter to generate HTML reports for each metric with pretty graphs.
|
|
57
|
+
|
|
58
|
+
These reports are generated in metric_fu's output directory (```tmp/metric_fu/output```) by default. You can customize the output directory by specifying an out directory at the command line
|
|
59
|
+
using a relative path:
|
|
60
|
+
|
|
61
|
+
metric_fu --out custom_directory # outputs to tmp/metric_fu/custom_directory
|
|
62
|
+
|
|
63
|
+
or a full path:
|
|
64
|
+
|
|
65
|
+
metric_fu --out /home/metrics # outputs to /home/metrics
|
|
66
|
+
|
|
67
|
+
You can specify a different formatter at the command line by referencing a built-in formatter or providing the fully-qualified name of a custom formatter.
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
metric_fu --format yaml --out custom_report.yml
|
|
71
|
+
or
|
|
72
|
+
|
|
73
|
+
metric_fu --format MyCustomFormatter
|
|
74
|
+
|
|
75
|
+
### Custom Formatters
|
|
76
|
+
|
|
77
|
+
You can customize metric_fu's output format with a custom formatter.
|
|
78
|
+
|
|
79
|
+
To create a custom formatter, you simply need to create a class
|
|
80
|
+
that takes an options hash and responds to one or more notifications:
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
class MyCustomFormatter
|
|
84
|
+
def initialize(opts={}); end # metric_fu will pass in an output param if provided.
|
|
85
|
+
|
|
86
|
+
# Should include one or more of...
|
|
87
|
+
def start; end # Sent before metric_fu starts metric measurements.
|
|
88
|
+
def start_metric(metric); end # Sent before individual metric is measured.
|
|
89
|
+
def finish_metric(metric); end # Sent after individual metric measurement is complete.
|
|
90
|
+
def finish; end # Sent after metric_fu has completed all measurements.
|
|
91
|
+
def display_results; end # Used to open results in browser, etc.
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
See [lib/metric_fu/formatter/](lib/metric_fu/formatter/) for examples.
|
|
96
|
+
|
|
97
|
+
metric_fu will attempt to require a custom formatter by
|
|
98
|
+
fully qualified name based on ruby search path. So if you include a custom
|
|
99
|
+
formatter as a gem in your Gemfile, you should be able to use it out of the box.
|
|
100
|
+
But you may find in certain cases that you need to add a require to
|
|
101
|
+
your .metrics configuration file.
|
|
102
|
+
|
|
103
|
+
For instance, to require a formatter in your app's lib directory:
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
require './lib/my_custom_formatter.rb'
|
|
107
|
+
```
|
|
108
|
+
|
|
50
109
|
### Configuration
|
|
51
110
|
|
|
52
111
|
see the .metrics file
|
data/TODO.md
CHANGED
|
@@ -84,6 +84,7 @@ instance variables and accessors
|
|
|
84
84
|
* CLI [Flog](https://github.com/seattlerb/flog/blob/master/lib/flog_cli.rb) Plugins [Flog](https://github.com/seattlerb/flog/blob/master/lib/flog_cli.rb#L34)
|
|
85
85
|
* Look into adding
|
|
86
86
|
* https://github.com/metricfu/code_statistics [1](https://github.com/cloudability/code_statistics)
|
|
87
|
+
* or extract from rails into a gem [rake task](https://github.com/rails/rails/blob/master/railties/lib/rails/tasks/statistics.rake) [can be modified by rspec](https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/tasks/rspec.rake#L38) with the [calculator](https://github.com/rails/rails/blob/master/railties/lib/rails/code_statistics_calculator.rb) and [class](https://github.com/rails/rails/blob/master/railties/lib/rails/code_statistics.rb)
|
|
87
88
|
* brakeman https://github.com/metricfu/brakeman
|
|
88
89
|
* laser https://github.com/metricfu/laser
|
|
89
90
|
* Other intersting libraries to consider:
|
data/bin/mf-saikuro
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
7a5e74c8b010bd9629e9cbdcf297cc1d75295338bb34a327a9ed57a742c5fc57107608bd148e31e5355263dc113841249be8719877a68fcb42271212edd71f13
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
#to use, from the app root run
|
|
4
|
+
# export BUNDLE_GEMFILE=$PWD/gemfiles/Gemfile.travis
|
|
5
|
+
# when done, unset BUNDLE_GEMFILE
|
|
6
|
+
# for 1.9.2 support because of https://github.com/railsbp/rails_best_practices/blob/master/rails_best_practices.gemspec
|
|
7
|
+
gem 'activesupport', '~> 3.2'
|
|
8
|
+
|
|
9
|
+
eval_gemfile File.expand_path('../../Gemfile', __FILE__)
|
data/lib/metric_fu.rb
CHANGED
|
@@ -25,7 +25,7 @@ module MetricFu
|
|
|
25
25
|
LIB_ROOT
|
|
26
26
|
end
|
|
27
27
|
class << self
|
|
28
|
-
%w(metrics reporting logging errors data_structures tasks).each do |dir|
|
|
28
|
+
%w(metrics formatter reporting logging errors data_structures tasks).each do |dir|
|
|
29
29
|
define_method("#{dir}_dir") do
|
|
30
30
|
File.join(lib_dir,dir)
|
|
31
31
|
end
|
data/lib/metric_fu/cli/client.rb
CHANGED
|
@@ -11,8 +11,8 @@ module MetricFu
|
|
|
11
11
|
def shutdown
|
|
12
12
|
@helper.shutdown
|
|
13
13
|
end
|
|
14
|
-
def run
|
|
15
|
-
options = @helper.process_options
|
|
14
|
+
def run(argv=ARGV.dup)
|
|
15
|
+
options = @helper.process_options(argv)
|
|
16
16
|
mf_debug "Got options #{options.inspect}"
|
|
17
17
|
if options[:run]
|
|
18
18
|
@helper.run(options)
|
data/lib/metric_fu/cli/helper.rb
CHANGED
|
@@ -35,15 +35,15 @@ module MetricFu
|
|
|
35
35
|
MetricFu.configuration.metrics.sort_by(&:to_s)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
def process_options(argv=
|
|
38
|
+
def process_options(argv=[])
|
|
39
39
|
options = MetricFu::Cli::MicroOptParse::Parser.new do |p|
|
|
40
40
|
p.banner = self.banner
|
|
41
41
|
p.version = self.version
|
|
42
|
-
p.option :run, "Run all metrics with defaults", :default =>
|
|
42
|
+
p.option :run, "Run all metrics with defaults", :default => true
|
|
43
43
|
metrics.each do |metric|
|
|
44
44
|
p.option metric.to_sym, "Enables or disables #{metric.to_s}", :default => true #, :value_in_set => [true, false]
|
|
45
45
|
end
|
|
46
|
-
p.option :open, "Open report in browser", :default => true
|
|
46
|
+
p.option :open, "Open report in browser (if supported by formatter)", :default => true
|
|
47
47
|
end.process!(argv)
|
|
48
48
|
options
|
|
49
49
|
end
|
data/lib/metric_fu/cli/parser.rb
CHANGED
|
@@ -24,22 +24,6 @@ module MetricFu
|
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def validate(options) # remove this method if you want fewer lines of code and don't need validations
|
|
28
|
-
options.each_pair do |key, value|
|
|
29
|
-
opt = @options.find_all{ |o| o[0] == key }.first
|
|
30
|
-
key = "--" << key.to_s.gsub("_", "-")
|
|
31
|
-
unless opt[2][:value_in_set].nil? || opt[2][:value_in_set].include?(value)
|
|
32
|
-
puts "Parameter for #{key} must be in [" << opt[2][:value_in_set].join(", ") << "]" ; exit(1)
|
|
33
|
-
end
|
|
34
|
-
unless opt[2][:value_matches].nil? || opt[2][:value_matches] =~ value
|
|
35
|
-
puts "Parameter for #{key} must match /" << opt[2][:value_matches].source << "/" ; exit(1)
|
|
36
|
-
end
|
|
37
|
-
unless opt[2][:value_satisfies].nil? || opt[2][:value_satisfies].call(value)
|
|
38
|
-
puts "Parameter for #{key} must satisfy given conditions (see description)" ; exit(1)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
27
|
def process!(arguments = ARGV)
|
|
44
28
|
@result = (@default_values || {}).clone # reset or new
|
|
45
29
|
@optionparser ||= OptionParser.new do |p| # prepare only once
|
|
@@ -55,6 +39,28 @@ module MetricFu
|
|
|
55
39
|
end
|
|
56
40
|
end
|
|
57
41
|
|
|
42
|
+
p.on("--format FORMAT",
|
|
43
|
+
"Specify the formatter to use for output.",
|
|
44
|
+
"This option can be specified multiple times.",
|
|
45
|
+
"Specify a built-in formatter from the list below,",
|
|
46
|
+
"or the fully-qualified class name of your own custom formatter.",
|
|
47
|
+
*format_descriptions) do |f|
|
|
48
|
+
@result[:format] ||= []
|
|
49
|
+
@result[:format] << [f]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
p.on("--out FILE|DIR",
|
|
53
|
+
"Specify the file or directory to use for output",
|
|
54
|
+
"This option applies to the previously",
|
|
55
|
+
"specified --format, or the default format",
|
|
56
|
+
"if no format is specified. Paths are relative to",
|
|
57
|
+
"#{Pathname.pwd.join(MetricFu.base_directory)}",
|
|
58
|
+
"Check the specific formatter\'s docs to see",
|
|
59
|
+
"whether to pass a file or a dir.") do |o|
|
|
60
|
+
@result[:format] ||= MetricFu::Formatter::DEFAULT
|
|
61
|
+
@result[:format].last << o
|
|
62
|
+
end
|
|
63
|
+
|
|
58
64
|
p.banner = @banner unless @banner.nil?
|
|
59
65
|
p.on_tail("-h", "--help", "Show this message") {puts p ; exit}
|
|
60
66
|
short = @used_short.include?("v") ? "-V" : "-v"
|
|
@@ -71,6 +77,21 @@ module MetricFu
|
|
|
71
77
|
validate(@result) if self.respond_to?("validate")
|
|
72
78
|
@result
|
|
73
79
|
end
|
|
80
|
+
|
|
81
|
+
# Build a nicely formatted list of built-in
|
|
82
|
+
# formatter keys and their descriptions
|
|
83
|
+
# @see MetricFu::Formatter::BUILTIN_FORMATS
|
|
84
|
+
# @example
|
|
85
|
+
# format_descriptions #=> [" yaml : Generates the raw output as yaml"]
|
|
86
|
+
# @return [Array<String>] in the form of
|
|
87
|
+
# " <key> : <description>."
|
|
88
|
+
def format_descriptions
|
|
89
|
+
formats = MetricFu::Formatter::BUILTIN_FORMATS
|
|
90
|
+
max = formats.keys.map{|s| s.length}.max
|
|
91
|
+
formats.keys.sort.map do |key|
|
|
92
|
+
" #{key}#{' ' * (max - key.length)} : #{formats[key][1]}"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
74
95
|
end
|
|
75
96
|
end
|
|
76
97
|
|
|
@@ -61,6 +61,7 @@ module MetricFu
|
|
|
61
61
|
set_directories
|
|
62
62
|
configure_template
|
|
63
63
|
add_promiscuous_instance_variable(:metrics, [])
|
|
64
|
+
add_promiscuous_instance_variable(:formatters, [])
|
|
64
65
|
add_promiscuous_instance_variable(:graphs, [])
|
|
65
66
|
add_promiscuous_instance_variable(:graph_engines, [])
|
|
66
67
|
add_promiscuous_method(:graph_engine)
|
|
@@ -90,6 +91,10 @@ module MetricFu
|
|
|
90
91
|
self.graphs = (graphs << metric).uniq
|
|
91
92
|
end
|
|
92
93
|
|
|
94
|
+
def add_formatter(format, output = nil)
|
|
95
|
+
@formatters << MetricFu::Formatter.class_for(format).new(output: output)
|
|
96
|
+
end
|
|
97
|
+
|
|
93
98
|
# e.g. :reek, {}
|
|
94
99
|
def configure_metric(metric, metric_configuration)
|
|
95
100
|
add_promiscuous_instance_variable(metric, metric_configuration)
|
|
@@ -126,6 +131,10 @@ module MetricFu
|
|
|
126
131
|
@mri ||= !!RedCard.check(:ruby)
|
|
127
132
|
end
|
|
128
133
|
|
|
134
|
+
def rubinius?
|
|
135
|
+
@rubinius ||= !!RedCard.check(:rubinius)
|
|
136
|
+
end
|
|
137
|
+
|
|
129
138
|
def platform #:nodoc:
|
|
130
139
|
# TODO, change
|
|
131
140
|
# RbConfig::CONFIG['ruby_install_name'].dup
|
|
@@ -208,6 +217,5 @@ module MetricFu
|
|
|
208
217
|
add_promiscuous_instance_variable(:code_dirs,['lib'])
|
|
209
218
|
end
|
|
210
219
|
end
|
|
211
|
-
|
|
212
220
|
end
|
|
213
221
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
module Constantize
|
|
3
|
+
# Copied from ActiveSupport and modified so as not to introduce a dependency.
|
|
4
|
+
# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L220
|
|
5
|
+
def constantize(camel_cased_word)
|
|
6
|
+
tries ||= 2
|
|
7
|
+
names = camel_cased_word.split('::')
|
|
8
|
+
names.shift if names.empty? || names.first.empty?
|
|
9
|
+
|
|
10
|
+
names.inject(Object) do |constant, name|
|
|
11
|
+
if constant == Object
|
|
12
|
+
constant.const_get(name)
|
|
13
|
+
else
|
|
14
|
+
candidate = constant.const_get(name)
|
|
15
|
+
next candidate if constant.const_defined?(name, false)
|
|
16
|
+
next candidate unless Object.const_defined?(name)
|
|
17
|
+
|
|
18
|
+
# Go down the ancestors to check it it's owned
|
|
19
|
+
# directly before we reach Object or the end of ancestors.
|
|
20
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
|
21
|
+
break const if ancestor == Object
|
|
22
|
+
break ancestor if ancestor.const_defined?(name, false)
|
|
23
|
+
const
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# owner is in Object, so raise
|
|
27
|
+
constant.const_get(name, false)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
rescue NameError
|
|
31
|
+
# May need to attempt to require the file and try again.
|
|
32
|
+
begin
|
|
33
|
+
require underscore(camel_cased_word)
|
|
34
|
+
rescue LoadError => e
|
|
35
|
+
mf_log e.message
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
if (tries -= 1).zero?
|
|
39
|
+
raise
|
|
40
|
+
else
|
|
41
|
+
retry
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Copied from active_support
|
|
46
|
+
# https://github.com/rails/rails/blob/51cd6bb829c418c5fbf75de1dfbb177233b1b154/activesupport/lib/active_support/inflector/methods.rb#L88
|
|
47
|
+
def underscore(camel_cased_word)
|
|
48
|
+
word = camel_cased_word.to_s.dup
|
|
49
|
+
word.gsub!(/::/, '/')
|
|
50
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
|
51
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
|
52
|
+
word.tr!("-", "_")
|
|
53
|
+
word.downcase!
|
|
54
|
+
word
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
# MetricFu::LineNumber
|
|
2
|
+
# (see #initialize)
|
|
1
3
|
require 'ruby_parser'
|
|
2
4
|
module MetricFu
|
|
3
5
|
class LineNumbers
|
|
4
6
|
|
|
7
|
+
# Parses ruby code to collect line numbers for class, module, and method definitions.
|
|
8
|
+
# Used by metrics that don't provide line numbers for class, module, or methods problems
|
|
9
|
+
# @param contents [String] a string of ruby code
|
|
10
|
+
# @param file_path [String] the file path for the contents, defaults to empty string
|
|
5
11
|
def initialize(contents,file_path='')
|
|
6
12
|
if contents.to_s.size.zero?
|
|
7
13
|
mf_log "NON PARSEABLE INPUT: File is empty at path #{file_path.inspect}\n\t#{caller.join("\n\t")}"
|
|
@@ -27,12 +33,20 @@ module MetricFu
|
|
|
27
33
|
@locations
|
|
28
34
|
end
|
|
29
35
|
|
|
36
|
+
# @param line_number [String]
|
|
37
|
+
# @return [Boolean] if the given line number is in a method
|
|
30
38
|
def in_method? line_number
|
|
31
39
|
!!@locations.detect do |method_name, line_number_range|
|
|
32
40
|
line_number_range.include?(line_number)
|
|
33
41
|
end
|
|
34
42
|
end
|
|
35
43
|
|
|
44
|
+
# @param line_number [Integer]
|
|
45
|
+
# @return [String, nil] the method which includes that line number, if any
|
|
46
|
+
# For all collected locations, find the first location where the line_number_range
|
|
47
|
+
# includes the line_number
|
|
48
|
+
# If a location is found, return its first element
|
|
49
|
+
# Else return nil
|
|
36
50
|
def method_at_line line_number
|
|
37
51
|
found_method_and_range = @locations.detect do |method_name, line_number_range|
|
|
38
52
|
line_number_range.include?(line_number)
|
|
@@ -44,6 +58,8 @@ module MetricFu
|
|
|
44
58
|
end
|
|
45
59
|
end
|
|
46
60
|
|
|
61
|
+
# @param method [String] the method name being queried
|
|
62
|
+
# @erturn [Integer, nil] the line number at which the given method is defined
|
|
47
63
|
def start_line_for_method(method)
|
|
48
64
|
return nil unless @locations.has_key?(method)
|
|
49
65
|
@locations[method].first
|
|
@@ -53,9 +69,9 @@ module MetricFu
|
|
|
53
69
|
|
|
54
70
|
def process_module(sexp)
|
|
55
71
|
module_name = sexp[1]
|
|
56
|
-
sexp.each_of_type(:class) do |
|
|
57
|
-
process_class(
|
|
58
|
-
hide_methods_from_next_round(
|
|
72
|
+
sexp.each_of_type(:class) do |exp|
|
|
73
|
+
process_class(exp, module_name)
|
|
74
|
+
hide_methods_from_next_round(exp)
|
|
59
75
|
end
|
|
60
76
|
process_class(sexp)
|
|
61
77
|
end
|