metric_fu 4.4.1 → 4.4.2
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 +14 -6
- data/CONTRIBUTORS +1 -0
- data/Gemfile +1 -1
- data/HISTORY.md +13 -0
- data/checksum/metric_fu-4.4.1.gem.sha512 +1 -0
- data/lib/metric_fu/cli/parser.rb +7 -0
- data/lib/metric_fu/data_structures/line_numbers.rb +70 -59
- data/lib/metric_fu/data_structures/location.rb +36 -20
- data/lib/metric_fu/data_structures/sexp_node.rb +89 -0
- data/lib/metric_fu/environment.rb +48 -0
- data/lib/metric_fu/io.rb +1 -7
- data/lib/metric_fu/metrics/base_template.rb +28 -9
- data/lib/metric_fu/metrics/hotspots/analysis/analyzed_problems.rb +8 -44
- data/lib/metric_fu/metrics/hotspots/analysis/analyzer_tables.rb +3 -0
- data/lib/metric_fu/metrics/hotspots/analysis/problems.rb +6 -2
- data/lib/metric_fu/metrics/hotspots/analysis/ranked_problem_location.rb +71 -0
- data/lib/metric_fu/metrics/hotspots/analysis/rankings.rb +8 -1
- data/lib/metric_fu/metrics/hotspots/hotspot_analyzer.rb +0 -1
- data/lib/metric_fu/metrics/hotspots/hotspots.rb +8 -3
- data/lib/metric_fu/metrics/hotspots/template_awesome/hotspots.html.erb +12 -12
- data/lib/metric_fu/metrics/saikuro/init.rb +3 -0
- data/lib/metric_fu/metrics/saikuro/parsing_element.rb +39 -0
- data/lib/metric_fu/metrics/saikuro/saikuro.rb +4 -145
- data/lib/metric_fu/metrics/saikuro/scratch_file.rb +114 -0
- data/lib/metric_fu/version.rb +1 -1
- data/spec/metric_fu/configuration_spec.rb +0 -7
- data/spec/metric_fu/formatter/html_spec.rb +0 -1
- data/spec/metric_fu/formatter/yaml_spec.rb +0 -1
- data/spec/metric_fu/metrics/base_template_spec.rb +1 -2
- data/spec/metric_fu/metrics/hotspots/analysis/analyzed_problems_spec.rb +8 -16
- data/spec/metric_fu/metrics/hotspots/hotspots_spec.rb +26 -69
- data/spec/metric_fu/metrics/saikuro/saikuro_spec.rb +5 -5
- data/spec/metric_fu/reporting/graphs/engines/gchart_spec.rb +1 -0
- data/spec/resources/yml/hotspots/generator.yml +47 -0
- data/spec/resources/yml/hotspots/generator_analysis.yml +53 -0
- data/spec/run_spec.rb +0 -1
- data/spec/support/helper_methods.rb +10 -0
- data/spec/support/suite.rb +13 -14
- metadata +35 -25
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MTFmYmRkMmExNTg1MDBhMDI0MTQ1OTFiMGJkNDc1MTY2OTdlYTJiNQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZDQ5OGMzN2QwNWE0M2JmMTM0ZTljYTA4OTFhYjBhNzgzZGVkYjYzMA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZTFlNDhmNDE1NjM1ZmMxODlmYjQ1NDZjMDI4MWE4NzBiMDFjNDc5YTBkODc2
|
10
|
+
NzZkZTA1ZTA1OWRhYjYyZmZmZDcxOGVmMGE1ODcxY2E1ZWEzMTliNDUxOTgx
|
11
|
+
NDdkYTNkNGViYTBmZmFhYWFjYzFlNTk1ZTNkZGRlOTFhY2VmNTc=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
OTY3Y2ZkMGVlZmJjNzM4MDQxZmMyNWIyNjU1OThmZTVmZDI4YTQyZjYxMDJi
|
14
|
+
MjYxMGQyYjM4YTcyNjliYTdlMjlkYzFmMjhlYjA0OTA2OTJiNDI1NzUwODM4
|
15
|
+
MzZkOTkyMzBmM2Q1N2IwYWNmMjc5MDQ2ZDJlYTFlNjhiNjkwZWI=
|
data/CONTRIBUTORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
George Erickson
|
data/Gemfile
CHANGED
@@ -14,7 +14,7 @@ group :test do
|
|
14
14
|
# https://github.com/kina/simplecov-rcov-text
|
15
15
|
gem 'simplecov-rcov-text'
|
16
16
|
end
|
17
|
-
gem "fakefs", :require => "fakefs/safe"
|
17
|
+
gem "fakefs", :require => "fakefs/safe", :platform => :ruby
|
18
18
|
gem 'json'
|
19
19
|
end
|
20
20
|
gemspec :path => File.expand_path('..', __FILE__)
|
data/HISTORY.md
CHANGED
@@ -10,6 +10,19 @@ As such, a _Feature_ would map to either major or minor. A _bug fix_ to a patch.
|
|
10
10
|
* Fixes
|
11
11
|
* Misc
|
12
12
|
|
13
|
+
### MetricFu [4.4.2 / 2013-09-25](https://github.com/metricfu/metric_fu/compare/v4.4.1...v4.4.2)
|
14
|
+
|
15
|
+
* Features
|
16
|
+
* Add --debug-info command line switch to get debug info for Issues. (calveto, #118)
|
17
|
+
* Fixes
|
18
|
+
* Return valid line locations for code with either no AST or nil nodes (Benjamin Fleischer, #137)
|
19
|
+
* Only use FakeFS on MRI. Avoid intermittent failures on JRuby or Rubinius (Benjamin Fleischer, #135)
|
20
|
+
* Hotspots no longer serialize actual classes to YAML. (Benjamin Fleischer, #128)
|
21
|
+
* Misc
|
22
|
+
* Extract SexpNode class from LineNumbers to handle Sexp Processing (Benjamin Fleischer, #137)
|
23
|
+
* Separate out Hotspot ranked problem location and misc code improvements (Benjamin Fleischer, #128)
|
24
|
+
* Identify directories with code to analyze by checking if they exist. (No longer use :rails? as a proxy for checking if we should run on 'app'). (George Erickson, #129)
|
25
|
+
|
13
26
|
### MetricFu [4.4.1 / 2013-08-29](https://github.com/metricfu/metric_fu/compare/v4.4.0...v4.4.1)
|
14
27
|
|
15
28
|
* Features
|
@@ -0,0 +1 @@
|
|
1
|
+
bbcd106dba00bcf0c1bfe8562d012a82f0945d8388bcd768598b872c35655668bfc9d0c1e7b0d67369713902dd9f1dd6fba9b83b21d79fe8ee774a2f8fa2defe
|
data/lib/metric_fu/cli/parser.rb
CHANGED
@@ -65,6 +65,7 @@ module MetricFu
|
|
65
65
|
p.on_tail("-h", "--help", "Show this message") {puts p ; exit}
|
66
66
|
short = @used_short.include?("v") ? "-V" : "-v"
|
67
67
|
p.on_tail(short, "--version", "Print version") {puts @version ; exit} unless @version.nil?
|
68
|
+
p.on_tail("--debug-info", "Print debug info") { debug_info; exit }
|
68
69
|
@default_values = @result.clone # save default values to reset @result in subsequent calls
|
69
70
|
end
|
70
71
|
|
@@ -78,6 +79,12 @@ module MetricFu
|
|
78
79
|
@result
|
79
80
|
end
|
80
81
|
|
82
|
+
def debug_info
|
83
|
+
extend(MetricFu::Environment)
|
84
|
+
require 'pp'
|
85
|
+
pp debug_info
|
86
|
+
end
|
87
|
+
|
81
88
|
# Build a nicely formatted list of built-in
|
82
89
|
# formatter keys and their descriptions
|
83
90
|
# @see MetricFu::Formatter::BUILTIN_FORMATS
|
@@ -1,63 +1,39 @@
|
|
1
|
-
|
2
|
-
# (see #initialize)
|
3
|
-
require 'ruby_parser'
|
1
|
+
MetricFu.data_structures_require { 'sexp_node' }
|
4
2
|
module MetricFu
|
5
3
|
class LineNumbers
|
4
|
+
attr_reader :file_path
|
6
5
|
|
7
6
|
# Parses ruby code to collect line numbers for class, module, and method definitions.
|
8
7
|
# Used by metrics that don't provide line numbers for class, module, or methods problems
|
9
8
|
# @param contents [String] a string of ruby code
|
10
9
|
# @param file_path [String] the file path for the contents, defaults to empty string
|
11
10
|
def initialize(contents,file_path='')
|
11
|
+
@file_path = file_path
|
12
|
+
@locations = {}
|
12
13
|
if contents.to_s.size.zero?
|
13
14
|
mf_log "NON PARSEABLE INPUT: File is empty at path #{file_path.inspect}\n\t#{caller.join("\n\t")}"
|
14
15
|
else
|
15
|
-
|
16
|
-
@locations = {}
|
17
|
-
file_sexp = rp.parse(contents)
|
18
|
-
case file_sexp[0]
|
19
|
-
when nil
|
20
|
-
mf_log "No ruby code found in #{file_path}"
|
21
|
-
when :class
|
22
|
-
process_class(file_sexp)
|
23
|
-
when :module
|
24
|
-
process_module(file_sexp)
|
25
|
-
else
|
26
|
-
mf_debug "SEXP: Parsing line numbers for classes in sexp type #{file_sexp[0].inspect}"
|
27
|
-
mf_debug " in #{file_path}"
|
28
|
-
file_sexp.each_of_type(:module) { |sexp| process_class(sexp) }
|
29
|
-
file_sexp.each_of_type(:class) { |sexp| process_class(sexp) }
|
30
|
-
end
|
16
|
+
parse_code(contents)
|
31
17
|
end
|
32
|
-
rescue Exception => e
|
33
|
-
#catch errors for files ruby_parser fails on
|
34
|
-
mf_log "RUBY PARSE FAILURE: #{e.class}\t#{e.message}\tFILE:#{file_path}\tSEXP:#{file_sexp.inspect}\n\tCONTENT:#{contents.inspect}\n\t#{e.backtrace}"
|
35
|
-
@locations
|
36
18
|
end
|
37
19
|
|
38
|
-
# @param line_number [
|
20
|
+
# @param line_number [Integer]
|
39
21
|
# @return [Boolean] if the given line number is in a method
|
40
|
-
def in_method?
|
41
|
-
|
42
|
-
line_number_range.include?(line_number)
|
43
|
-
end
|
22
|
+
def in_method?(line_number)
|
23
|
+
not method_at_line(line_number) == :no_method_at_line
|
44
24
|
end
|
45
25
|
|
46
26
|
# @param line_number [Integer]
|
47
27
|
# @return [String, nil] the method which includes that line number, if any
|
48
|
-
# For all collected locations, find the first location
|
49
|
-
# includes the line_number
|
50
|
-
# If a location is found, return
|
51
|
-
# Else return
|
52
|
-
def method_at_line
|
53
|
-
|
28
|
+
# For all collected locations, find the first location
|
29
|
+
# where the line_number_range includes the line_number.
|
30
|
+
# If a location is found, return the method name (first element)
|
31
|
+
# Else return :no_method_at_line
|
32
|
+
def method_at_line(line_number)
|
33
|
+
default_proc = ->{ [:no_method_at_line] }
|
34
|
+
@locations.detect(default_proc) do |method_name, line_number_range|
|
54
35
|
line_number_range.include?(line_number)
|
55
|
-
end
|
56
|
-
if found_method_and_range
|
57
|
-
found_method_and_range.first
|
58
|
-
else
|
59
|
-
nil
|
60
|
-
end
|
36
|
+
end.first
|
61
37
|
end
|
62
38
|
|
63
39
|
# @param method [String] the method name being queried
|
@@ -69,33 +45,68 @@ module MetricFu
|
|
69
45
|
|
70
46
|
private
|
71
47
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
48
|
+
def parse_code(contents)
|
49
|
+
file_sexp = MetricFu::SexpNode.parse(contents)
|
50
|
+
file_sexp && process_ast(file_sexp)
|
51
|
+
rescue => e
|
52
|
+
#catch errors for files ruby_parser fails on
|
53
|
+
mf_log "RUBY PARSE FAILURE: #{e.class}\t#{e.message}\tFILE:#{file_path}\tSEXP:#{file_sexp.inspect}\n\tCONTENT:#{contents.inspect}\n\t#{e.backtrace}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def process_ast(file_sexp)
|
57
|
+
node = MetricFu::SexpNode.new(file_sexp)
|
58
|
+
case node.node_type
|
59
|
+
when nil
|
60
|
+
mf_log "No ruby code found in #{file_path}"
|
61
|
+
when :class
|
62
|
+
process_class(node)
|
63
|
+
when :module
|
64
|
+
process_module(node)
|
65
|
+
else
|
66
|
+
mf_debug "SEXP: Parsing line numbers for classes in sexp type #{node.node_type.inspect}"
|
67
|
+
mf_debug " in #{file_path}"
|
68
|
+
node.each_module {|child_node| process_class(child_node) }
|
69
|
+
node.each_class {|child_node| process_class(child_node) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def process_module(module_node)
|
74
|
+
module_name = module_node.name
|
75
|
+
module_node.each_class do |class_node|
|
76
|
+
process_class(class_node, module_name)
|
77
|
+
class_node.hide_methods_from_next_round
|
77
78
|
end
|
78
|
-
process_class(
|
79
|
+
process_class(module_node)
|
79
80
|
end
|
80
81
|
|
81
|
-
def process_class(
|
82
|
-
class_name =
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
sexp.each_of_type(:defs) { |s| @locations["#{module_name_string}#{class_name}::#{s[2]}"] = (s.line)..(s.last.line) }
|
82
|
+
def process_class(class_node, module_name=nil)
|
83
|
+
class_name = class_node.name
|
84
|
+
process_singleton_methods(class_node, class_name)
|
85
|
+
process_instance_methods( class_node, class_name, module_name)
|
86
|
+
process_class_methods( class_node, class_name, module_name)
|
87
87
|
end
|
88
88
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
89
|
+
def process_singleton_methods(class_node, class_name)
|
90
|
+
class_node.each_singleton_class do |singleton_node|
|
91
|
+
singleton_node.each_singleton_method do |singleton_method_node|
|
92
|
+
singleton_method_name = singleton_method_node.full_name(class_name)
|
93
|
+
@locations[singleton_method_name] = singleton_method_node.line_range
|
94
|
+
end
|
93
95
|
end
|
94
96
|
end
|
95
97
|
|
96
|
-
def
|
97
|
-
|
98
|
-
|
98
|
+
def process_instance_methods(class_node, class_name, module_name)
|
99
|
+
class_node.each_instance_method do |instance_method_node|
|
100
|
+
instance_method_name = instance_method_node.full_name(module_name, class_name)
|
101
|
+
@locations[instance_method_name] = instance_method_node.line_range
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def process_class_methods(class_node, class_name, module_name)
|
106
|
+
class_node.each_class_method do |class_method_node|
|
107
|
+
class_method_name = class_method_node.full_name(module_name, class_name)
|
108
|
+
@locations[class_method_name] = class_method_node.line_range
|
109
|
+
end
|
99
110
|
end
|
100
111
|
|
101
112
|
end
|
@@ -3,34 +3,58 @@ module MetricFu
|
|
3
3
|
include Comparable
|
4
4
|
|
5
5
|
attr_accessor :file_path, :file_name, :line_number,
|
6
|
-
:class_name, :method_name, :simple_method_name, :hash
|
6
|
+
:class_name, :method_name, :simple_method_name, :hash, :hash_key
|
7
7
|
|
8
8
|
def self.get(file_path, class_name, method_name)
|
9
9
|
location = new(file_path, class_name, method_name)
|
10
10
|
@@locations ||= {}
|
11
|
-
@@locations.fetch(location.
|
12
|
-
@@locations[location.
|
11
|
+
@@locations.fetch(location.hash_key) do
|
12
|
+
@@locations[location.hash_key] = location
|
13
13
|
location.finalize
|
14
14
|
location
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
def initialize(file_path, class_name, method_name)
|
19
|
-
@file_path
|
19
|
+
@file_path = file_path
|
20
20
|
@file_name, @line_number = file_path.to_s.split(/:/)
|
21
|
-
@class_name
|
22
|
-
@method_name
|
23
|
-
@simple_method_name
|
24
|
-
@
|
21
|
+
@class_name = class_name
|
22
|
+
@method_name = method_name
|
23
|
+
@simple_method_name = @method_name.to_s.sub(@class_name.to_s,'')
|
24
|
+
@hash_key = to_key
|
25
|
+
@hash = @hash_key.hash
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
+
def to_hash
|
29
|
+
hash = {
|
30
|
+
"class_name" => class_name,
|
31
|
+
"method_name" => method_name,
|
32
|
+
"file_path" => file_path,
|
33
|
+
'file_name' => file_name,
|
34
|
+
'line_number' => line_number,
|
35
|
+
'hash_key' => hash_key,
|
36
|
+
}
|
37
|
+
|
38
|
+
if method_name.to_s.size > 0
|
39
|
+
hash = hash.merge("simple_method_name" => simple_method_name)
|
40
|
+
else
|
41
|
+
hash
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# defining :eql? and :hash to use Location as a hash key
|
28
46
|
def eql?(other)
|
29
|
-
# REMOVED per https://github.com/jscruggs/metric_fu/pull/67/files
|
30
|
-
# [self.file_path.to_s, self.class_name.to_s, self.method_name.to_s] == [other.file_path.to_s, other.class_name.to_s, other.method_name.to_s]
|
31
47
|
@hash == other.hash
|
32
48
|
end
|
33
|
-
|
49
|
+
|
50
|
+
def <=>(other)
|
51
|
+
self.hash <=> other.hash
|
52
|
+
end
|
53
|
+
|
54
|
+
# Generates the @hash key
|
55
|
+
def to_key
|
56
|
+
[@file_path, @class_name, @method_name].inspect
|
57
|
+
end
|
34
58
|
|
35
59
|
def self.for(class_or_method_name)
|
36
60
|
class_or_method_name = strip_modules(class_or_method_name)
|
@@ -61,14 +85,6 @@ module MetricFu
|
|
61
85
|
self.get(nil, class_name, method_name)
|
62
86
|
end
|
63
87
|
|
64
|
-
def <=>(other)
|
65
|
-
[self.file_path.to_s, self.class_name.to_s, self.method_name.to_s] <=> [other.file_path.to_s, other.class_name.to_s, other.method_name.to_s]
|
66
|
-
end
|
67
|
-
|
68
|
-
def to_key
|
69
|
-
[@file_path, @class_name, @method_name]
|
70
|
-
end
|
71
|
-
|
72
88
|
def finalize
|
73
89
|
@file_path &&= @file_path.clone
|
74
90
|
@file_name &&= @file_name.clone
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'ruby_parser'
|
2
|
+
module MetricFu
|
3
|
+
SexpNode = Struct.new(:sexp) do
|
4
|
+
# @return file_sexp
|
5
|
+
def self.parse(contents)
|
6
|
+
rp = RubyParser.new
|
7
|
+
rp.parse(contents)
|
8
|
+
end
|
9
|
+
def nil?
|
10
|
+
sexp.nil?
|
11
|
+
end
|
12
|
+
def node_type
|
13
|
+
sexp[0]
|
14
|
+
end
|
15
|
+
def name
|
16
|
+
sexp[1]
|
17
|
+
end
|
18
|
+
def each_of_type(type,node_class=SexpNode)
|
19
|
+
sexp.each_of_type(type) do |child_sexp|
|
20
|
+
yield node_class.new(child_sexp)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
def each_module(&block)
|
24
|
+
each_of_type(:module,&block)
|
25
|
+
end
|
26
|
+
def each_class(&block)
|
27
|
+
each_of_type(:class,&block)
|
28
|
+
end
|
29
|
+
def each_singleton_class(&block)
|
30
|
+
each_of_type(:sclass,SingletonMethodNode,&block)
|
31
|
+
end
|
32
|
+
def each_instance_method(&block)
|
33
|
+
each_of_type(:defn,InstanceMethodNode,&block)
|
34
|
+
end
|
35
|
+
def each_class_method(&block)
|
36
|
+
each_of_type(:defs,ClassMethodNode,&block)
|
37
|
+
end
|
38
|
+
def first_line
|
39
|
+
sexp.line
|
40
|
+
end
|
41
|
+
def last_line
|
42
|
+
sexp.last.line
|
43
|
+
end
|
44
|
+
def line_range
|
45
|
+
(first_line..last_line)
|
46
|
+
end
|
47
|
+
def hide_methods_from_next_round
|
48
|
+
sexp.find_and_replace_all(:defn, :ignore_me)
|
49
|
+
sexp.find_and_replace_all(:defs, :ignore_me)
|
50
|
+
end
|
51
|
+
def full_method_name(method_separator, class_name, module_name=nil)
|
52
|
+
[module_namespace(module_name), class_name, method_separator, name].join
|
53
|
+
end
|
54
|
+
def module_namespace(module_name=nil)
|
55
|
+
if module_name.nil?
|
56
|
+
nil
|
57
|
+
else
|
58
|
+
[module_name,class_method_separator].join
|
59
|
+
end
|
60
|
+
end
|
61
|
+
def instance_method_separator
|
62
|
+
'#'
|
63
|
+
end
|
64
|
+
def class_method_separator
|
65
|
+
'::'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
class ClassMethodNode < SexpNode
|
69
|
+
def name
|
70
|
+
sexp[2]
|
71
|
+
end
|
72
|
+
def full_name(module_name, class_name)
|
73
|
+
full_method_name(class_method_separator, class_name, module_name)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
class InstanceMethodNode < SexpNode
|
77
|
+
def full_name(module_name, class_name)
|
78
|
+
full_method_name(instance_method_separator, class_name, module_name)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
class SingletonMethodNode < SexpNode
|
82
|
+
def full_name(class_name)
|
83
|
+
full_method_name(class_method_separator, class_name)
|
84
|
+
end
|
85
|
+
def each_singleton_method(&block)
|
86
|
+
each_of_type(:defn,SingletonMethodNode,&block)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'redcard'
|
2
|
+
require 'rbconfig'
|
2
3
|
MetricFu.logging_require { 'mf_debugger' }
|
3
4
|
module MetricFu
|
4
5
|
module Environment
|
@@ -66,10 +67,57 @@ module MetricFu
|
|
66
67
|
false
|
67
68
|
end
|
68
69
|
end
|
70
|
+
|
69
71
|
def platform #:nodoc:
|
70
72
|
return RUBY_PLATFORM
|
71
73
|
end
|
72
74
|
|
75
|
+
def version
|
76
|
+
MetricFu::VERSION
|
77
|
+
end
|
78
|
+
|
79
|
+
def environment_details
|
80
|
+
@environment_details ||= {
|
81
|
+
'VERBOSE' => $VERBOSE.inspect,
|
82
|
+
'External Encoding' => Encoding.default_external.to_s,
|
83
|
+
'Internal Encoding' => Encoding.default_internal.to_s,
|
84
|
+
'Host Architecture' => RbConfig::CONFIG['build'],
|
85
|
+
'Ruby Prefix' => RbConfig::CONFIG['prefix'],
|
86
|
+
'Ruby Options' => ENV.keys.grep(/RUBYOPT/).map{|key| "#{key}=#{ENV[key]}" }.join(', '),
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
# To consider
|
91
|
+
# $LOADED_FEATURES
|
92
|
+
# $LOAD_PATH
|
93
|
+
def ruby_details
|
94
|
+
@ruby_details ||= {
|
95
|
+
'Engine' => ruby_flavor,
|
96
|
+
'Version' => ruby_version,
|
97
|
+
'Patchlevel' => (defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL),
|
98
|
+
'Ripper Support' => supports_ripper?,
|
99
|
+
'Rubygems Version' => Gem::VERSION,
|
100
|
+
'Long Description' => (defined?(RUBY_DESCRIPTION) ? RUBY_DESCRIPTION : platform),
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
def library_details
|
105
|
+
@library_details ||= {
|
106
|
+
'Version' => version,
|
107
|
+
'Verbose Mode' => verbose,
|
108
|
+
'Enabled Metrics' => MetricFu::Metric.enabled_metrics.map(&:name),
|
109
|
+
# 'Dependencies' => `gem dependency metric_fu`, # TODO how should we handle this?
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def debug_info
|
114
|
+
@debug_info ||= {
|
115
|
+
'Ruby' => ruby_details,
|
116
|
+
'Environment' => environment_details,
|
117
|
+
'MetricFu' => library_details,
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
73
121
|
def osx?
|
74
122
|
@osx ||= platform.include?('darwin')
|
75
123
|
end
|