metric_fu 4.4.1 → 4.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|