jscruggs-metric_fu 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/HISTORY +13 -0
  2. data/README +1 -1
  3. data/Rakefile +1 -29
  4. data/TODO +1 -2
  5. data/lib/base/base_template.rb +18 -6
  6. data/lib/base/configuration.rb +22 -2
  7. data/lib/base/generator.rb +15 -2
  8. data/lib/base/graph.rb +37 -0
  9. data/lib/generators/churn.rb +6 -1
  10. data/lib/generators/flay.rb +5 -0
  11. data/lib/generators/flog.rb +6 -0
  12. data/lib/generators/rcov.rb +10 -0
  13. data/lib/generators/reek.rb +5 -0
  14. data/lib/generators/roodi.rb +7 -0
  15. data/lib/generators/saikuro.rb +184 -187
  16. data/lib/graphs/flay_grapher.rb +34 -0
  17. data/lib/graphs/flog_grapher.rb +37 -0
  18. data/lib/graphs/rcov_grapher.rb +34 -0
  19. data/lib/graphs/reek_grapher.rb +44 -0
  20. data/lib/graphs/roodi_grapher.rb +34 -0
  21. data/lib/metric_fu.rb +4 -0
  22. data/lib/templates/awesome/awesome_template.rb +30 -0
  23. data/lib/templates/awesome/churn.html.erb +19 -0
  24. data/lib/templates/awesome/default.css +75 -0
  25. data/lib/templates/awesome/flay.html.erb +27 -0
  26. data/lib/templates/awesome/flog.html.erb +46 -0
  27. data/lib/templates/awesome/index.html.erb +28 -0
  28. data/lib/templates/awesome/layout.html.erb +27 -0
  29. data/lib/templates/awesome/rcov.html.erb +36 -0
  30. data/lib/templates/awesome/reek.html.erb +34 -0
  31. data/lib/templates/awesome/roodi.html.erb +21 -0
  32. data/lib/templates/awesome/saikuro.html.erb +71 -0
  33. data/lib/templates/awesome/stats.html.erb +41 -0
  34. data/lib/templates/standard/churn.html.erb +1 -0
  35. data/lib/templates/standard/flay.html.erb +1 -0
  36. data/lib/templates/standard/flog.html.erb +3 -2
  37. data/lib/templates/standard/rcov.html.erb +5 -4
  38. data/lib/templates/standard/reek.html.erb +1 -0
  39. data/lib/templates/standard/roodi.html.erb +1 -0
  40. data/lib/templates/standard/saikuro.html.erb +1 -0
  41. data/lib/templates/standard/stats.html.erb +1 -0
  42. data/spec/base/base_template_spec.rb +35 -14
  43. data/spec/base/configuration_spec.rb +4 -4
  44. data/spec/base/generator_spec.rb +23 -1
  45. data/spec/base/md5_tracker_spec.rb +1 -1
  46. data/spec/base/report_spec.rb +1 -1
  47. data/spec/generators/churn_spec.rb +8 -8
  48. data/spec/generators/flay_spec.rb +4 -1
  49. data/spec/generators/flog_spec.rb +10 -2
  50. data/spec/generators/reek_spec.rb +2 -1
  51. data/spec/generators/saikuro_spec.rb +22 -17
  52. data/spec/generators/stats_spec.rb +1 -1
  53. data/tasks/metric_fu.rake +8 -1
  54. data/vendor/_fonts/monaco.ttf +0 -0
  55. metadata +30 -20
  56. data/tasks/railroad.rake +0 -39
data/HISTORY CHANGED
@@ -1,3 +1,16 @@
1
+ === MetricFu 1.1.0 / 2009-6-22
2
+
3
+ * Flog, flay, reek, roodi, and rcov reports now graph progress over time. Well done Nick Quarantos and Edouard Brière.
4
+ * 'Awesome' template has been brought in so that reports look 90% less 'ghetto.' Also done by Nick Quarantos and Edouard Brière.
5
+ * Added links to TextMate (which keep getting removed. Probably by me. Sorry.) -- David Chelimsky
6
+ * Fixed a bug for scratch files which have a size of 0 -- Kevin Hall
7
+ * Changed gem dependencies from install-time in gemspec to runtime when each of the generators is loaded. This allows use of github gems (i.e. relevance-rcov instead of rcov) and also allows you to install only the gems for the metrics you plan on using. -- Alex Rothenberg
8
+ * Empty Flog file fix -- Adam Bair
9
+ * Added a simple fix for cases where Saikuro results with nested information -- Randy Souza
10
+ * Fixed rcov configuration so it ignores library files on Linux -- Diego Carrion
11
+ * Changing churn so that it still works deeper than the git root directory -- Andrew Timberlake
12
+ * Andrew Timberlake also made some nice changes to the base template which kinda of got overshadowed by the 'awesome' template. Sorry about that Andrew.
13
+
1
14
  === MetricFu 1.0.2 / 2009-5-11
2
15
 
3
16
  * Fixing problems with Reek new line character (thanks to all who pointed this out)
data/README CHANGED
@@ -1 +1 @@
1
- See http://metric-fu.rubyforge.org/ for documentation, or the HISTORY file for a change log.
1
+ See http://metric-fu.rubyforge.org/ for documentation, or the HISTORY file for a change log.
data/Rakefile CHANGED
@@ -12,35 +12,7 @@ Spec::Rake::SpecTask.new(:spec) do |t|
12
12
  end
13
13
 
14
14
  MetricFu::Configuration.run do |config|
15
- end
16
-
17
- namespace :metrics do
18
- desc "Generate all reports"
19
- task :all do
20
- MetricFu.metrics.each {|metric| MetricFu.report.add(metric) }
21
- MetricFu.report.save_output(MetricFu.report.to_yaml,
22
- MetricFu.base_directory,
23
- 'report.yml')
24
- MetricFu.report.save_templatized_report
25
- if MetricFu.report.open_in_browser?
26
- MetricFu.report.show_in_browser(MetricFu.output_directory)
27
- end
28
- end
29
-
30
- MetricFu.metrics.each do |metric|
31
- desc "Generate report for #{metric}"
32
- task metric do
33
-
34
- MetricFu.report.add(metric)
35
- MetricFu.report.save_output(MetricFu.report.to_yaml,
36
- MetricFu.base_directory,
37
- 'report.yml')
38
- MetricFu.report.save_templatized_report
39
- if MetricFu.report.open_in_browser?
40
- MetricFu.report.show_in_browser(MetricFu.output_directory)
41
- end
42
- end
43
- end
15
+ config.template_class = AwesomeTemplate
44
16
  end
45
17
 
46
18
  task :default => [:"metrics:all"]
data/TODO CHANGED
@@ -1,9 +1,7 @@
1
1
  == TODO list
2
2
 
3
3
  * Color code flog results with scale from: http://jakescruggs.blogspot.com/2008/08/whats-good-flog-score.html
4
- * Extract functionality from rake files and put under test
5
4
  * Integrate Flog, Saikuro, and Coverage into one report so you can see methods that have high complexity and low coverage (this is a big one)
6
- * Integrate MD5 hashing with remainder of reports
7
5
  * Move HTML out of code and into templates/
8
6
  * Replace #generate_report with #new on each metric class
9
7
  * Make each class descend from MetricFu::CodeMetric
@@ -12,3 +10,4 @@
12
10
  * Add flay specs that run flay
13
11
  * Convert readme to markdown and rename to README.mkdn so github will render it
14
12
  * Saikuro.rb falls over if tries to parse an empty file. Fair enough. We shouldn't feed it empty files
13
+ * Make running metric_fu on metric_fu less embarrassing
@@ -99,16 +99,28 @@ module MetricFu
99
99
  #
100
100
  # @return String
101
101
  # An anchor link to a textmate reference or a file reference
102
- def link_to_filename(name, line = nil)
103
- filename = File.expand_path(name)
102
+ def link_to_filename(name, line = nil, link_content = nil)
103
+ "<a href='#{file_url(name, line)}'>#{link_content(name, line, link_content)}</a>"
104
+ end
105
+
106
+ def link_content(name, line=nil, link_content=nil) # :nodoc:
107
+ if link_content
108
+ link_content
109
+ elsif line
110
+ "#{name}:#{line}"
111
+ else
112
+ name
113
+ end
114
+ end
115
+
116
+ def file_url(name, line) # :nodoc:
117
+ filename = File.expand_path(name.gsub(/^\//, ''))
104
118
  if MetricFu.configuration.platform.include?('darwin')
105
- "<a href='txmt://open/?url=file://" \
106
- +"#{filename}&line=#{line}'>#{name}:#{line}</a>"
119
+ "txmt://open/?url=file://#{filename}" << (line ? "&line=#{line}" : "")
107
120
  else
108
- "<a href='file://#{filename}'>#{name}:#{line}</a>"
121
+ "file://#{filename}"
109
122
  end
110
123
  end
111
-
112
124
 
113
125
  # Provides a brain dead way to cycle between two values during
114
126
  # an iteration of some sort. Pass in the first_value, the second_value,
@@ -8,6 +8,7 @@ module MetricFu
8
8
  AVAILABLE_METRICS = [:churn, :flog, :flay, :reek,
9
9
  :roodi, :saikuro, :rcov]
10
10
 
11
+ AVAILABLE_GRAPHS = [:flog, :flay, :reek, :roodi, :rcov]
11
12
 
12
13
  # The @@configuration class variable holds a global type configuration
13
14
  # object for any parts of the system to use.
@@ -118,12 +119,14 @@ module MetricFu
118
119
  @base_directory = ENV['CC_BUILD_ARTIFACTS'] || 'tmp/metric_fu'
119
120
  @scratch_directory = File.join(@base_directory, 'scratch')
120
121
  @output_directory = File.join(@base_directory, 'output')
122
+ @data_directory = File.join('tmp/metric_fu', '_data')
121
123
  @metric_fu_root_directory = File.join(File.dirname(__FILE__),
122
124
  '..', '..')
123
125
  @template_directory = File.join(@metric_fu_root_directory,
124
126
  'lib', 'templates')
125
- @template_class = StandardTemplate
127
+ @template_class = AwesomeTemplate
126
128
  set_metrics
129
+ set_graphs
127
130
  set_code_dirs
128
131
  @flay = { :dirs_to_flay => @code_dirs }
129
132
  @flog = { :dirs_to_flog => @code_dirs }
@@ -146,7 +149,20 @@ module MetricFu
146
149
  "--no-color",
147
150
  "--profile",
148
151
  "--rails",
149
- "--exclude /gems/,/Library/,spec"]}
152
+ "--exclude /gems/,/Library/,/usr/,spec"]}
153
+
154
+ @graph_theme = { :colors => %w(orange purple green white red blue pink yellow),
155
+ :marker_color => 'blue',
156
+ :background_colors => %w(white white)}
157
+
158
+ relative_font_path = [File.dirname(__FILE__), '..', '..', 'vendor', '_fonts', 'monaco.ttf']
159
+ @graph_font = File.expand_path(File.join(relative_font_path))
160
+ @graph_size = "1000x400"
161
+ @graph_title_font_size = 12
162
+ @graph_legend_box_size = 12
163
+ @graph_legend_font_size = 10
164
+ @graph_marker_font_size = 10
165
+
150
166
  end
151
167
 
152
168
  # Perform a simple check to try and guess if we're running
@@ -166,6 +182,10 @@ module MetricFu
166
182
  @metrics = MetricFu::AVAILABLE_METRICS
167
183
  end
168
184
  end
185
+
186
+ def set_graphs
187
+ @graphs = MetricFu::AVAILABLE_GRAPHS
188
+ end
169
189
 
170
190
  # Add the 'app' directory if we're running within rails.
171
191
  def set_code_dirs
@@ -33,8 +33,10 @@ module MetricFu
33
33
  attr_reader :report, :template
34
34
 
35
35
  def initialize(options={})
36
+ self.class.verify_dependencies!
36
37
  create_metric_dir_if_missing
37
38
  create_output_dir_if_missing
39
+ create_data_dir_if_missing
38
40
  end
39
41
 
40
42
  # Creates a new generator and returns the output of the
@@ -82,6 +84,12 @@ module MetricFu
82
84
  FileUtils.mkdir_p(MetricFu.output_directory, :verbose => false)
83
85
  end
84
86
  end
87
+
88
+ def create_data_dir_if_missing #:nodoc:
89
+ unless File.directory?(MetricFu.data_directory)
90
+ FileUtils.mkdir_p(MetricFu.data_directory, :verbose => false)
91
+ end
92
+ end
85
93
 
86
94
  # @return String
87
95
  # The path of the metric directory this class is using.
@@ -119,6 +127,11 @@ module MetricFu
119
127
  def round_to_tenths(decimal)
120
128
  (decimal * 10).round / 10.0
121
129
  end
130
+
131
+ # Allows subclasses to check for required gems
132
+ def self.verify_dependencies!
133
+ true
134
+ end
122
135
 
123
136
  def emit #:nodoc:
124
137
  raise <<-EOF
@@ -135,8 +148,8 @@ module MetricFu
135
148
  information.
136
149
  EOF
137
150
  end
138
-
139
- def to_h #:nodoc:
151
+
152
+ def to_graph #:nodoc:
140
153
  raise <<-EOF
141
154
  This method must be implemented by a concrete class descending
142
155
  from Generator. See generator class documentation for more
@@ -0,0 +1,37 @@
1
+ module MetricFu
2
+
3
+ def self.graph
4
+ @graph ||= Graph.new
5
+ end
6
+
7
+ class Graph
8
+
9
+ attr_accessor :clazz
10
+
11
+ def initialize
12
+ self.clazz = []
13
+ end
14
+
15
+ def add(graph_type)
16
+ grapher_name = graph_type.to_s.capitalize + "Grapher"
17
+ self.clazz.push MetricFu.const_get(grapher_name).new
18
+ end
19
+
20
+
21
+ def generate
22
+ puts "Generating graphs"
23
+ Dir[File.join(MetricFu.data_directory, '*.yml')].sort.each do |metric_file|
24
+ puts "Generating graphs for #{metric_file}"
25
+ date = metric_file.split('/')[3].split('.')[0]
26
+ metrics = YAML::load(File.open(metric_file))
27
+
28
+ self.clazz.each do |grapher|
29
+ grapher.get_metrics(metrics, date)
30
+ end
31
+ end
32
+ self.clazz.each do |grapher|
33
+ grapher.graph!
34
+ end
35
+ end
36
+ end
37
+ end
@@ -4,9 +4,10 @@ module MetricFu
4
4
 
5
5
  class Churn < Generator
6
6
 
7
+
7
8
  def initialize(options={})
8
9
  super
9
- if File.exist?(".git")
10
+ if self.class.git?
10
11
  @source_control = Git.new(MetricFu.churn[:start_date])
11
12
  elsif File.exist?(".svn")
12
13
  @source_control = Svn.new(MetricFu.churn[:start_date])
@@ -16,6 +17,10 @@ module MetricFu
16
17
  @minimum_churn_count = MetricFu.churn[:minimum_churn_count] || 5
17
18
  end
18
19
 
20
+ def self.git?
21
+ system("git branch")
22
+ end
23
+
19
24
  def emit
20
25
  @changes = parse_log_for_changes.reject {|file, change_count| change_count < @minimum_churn_count}
21
26
  end
@@ -3,6 +3,11 @@ module MetricFu
3
3
 
4
4
  class Flay < Generator
5
5
 
6
+ def self.verify_dependencies!
7
+ `flay --help`
8
+ raise 'sudo gem install flay # if you want the flay tasks' unless $?.success?
9
+ end
10
+
6
11
  def emit
7
12
  files_to_flay = MetricFu.flay[:dirs_to_flay].map{|dir| Dir[File.join(dir, "**/*.rb")] }
8
13
  @output = `flay #{files_to_flay.join(" ")}`
@@ -3,6 +3,11 @@ module MetricFu
3
3
  class Flog < Generator
4
4
  attr_reader :pages
5
5
 
6
+ def self.verify_dependencies!
7
+ `flog --help`
8
+ raise 'sudo gem install flog # if you want the flog tasks' unless $?.success?
9
+ end
10
+
6
11
  SCORE_FORMAT = "%0.2f"
7
12
  METHOD_LINE_REGEX = /(\d+\.\d+):\s+([A-Za-z:]+#.*)/
8
13
  OPERATOR_LINE_REGEX = /\s*(\d+\.\d+):\s(.*)$/
@@ -28,6 +33,7 @@ module MetricFu
28
33
 
29
34
  def parse(text)
30
35
  summary, methods_summary = text.split "\n\n"
36
+ return unless summary
31
37
  score, average = summary.split("\n").map {|line| line[OPERATOR_LINE_REGEX, 1]}
32
38
  return nil unless score && methods_summary
33
39
  page = Flog::Page.new(score, average)
@@ -5,6 +5,16 @@ module MetricFu
5
5
  class Rcov < Generator
6
6
  NEW_FILE_MARKER = ("=" * 80) + "\n"
7
7
 
8
+ def self.verify_dependencies!
9
+ `flay --help`
10
+ unless $?.success?
11
+ if RUBY_PLATFORM =~ /java/
12
+ raise 'running in jruby - rcov tasks not available'
13
+ else
14
+ raise 'sudo gem install rcov # if you want the rcov tasks'
15
+ end
16
+ end
17
+ end
8
18
 
9
19
  class Line
10
20
  attr_accessor :content, :was_run
@@ -3,6 +3,11 @@ module MetricFu
3
3
  class Reek < Generator
4
4
  REEK_REGEX = /^(\S+) (.*) \((.*)\)$/
5
5
 
6
+ def self.verify_dependencies!
7
+ `reek --help`
8
+ raise 'sudo gem install reek # if you want the reek tasks' unless $?.success?
9
+ end
10
+
6
11
  def emit
7
12
  files_to_reek = MetricFu.reek[:dirs_to_reek].map{|dir| Dir[File.join(dir, "**/*.rb")] }
8
13
  @output = `reek #{files_to_reek.join(" ")}`
@@ -1,5 +1,12 @@
1
1
  module MetricFu
2
2
  class Roodi < Generator
3
+
4
+ def self.verify_dependencies!
5
+ `roodi --help`
6
+ raise 'sudo gem install roodi # if you want the roodi tasks' unless $?.success?
7
+ end
8
+
9
+
3
10
  def emit
4
11
  files_to_analyze = MetricFu.roodi[:dirs_to_roodi].map{|dir| Dir[File.join(dir, "**/*.rb")] }
5
12
  @output = `roodi #{files_to_analyze.join(" ")}`
@@ -1,211 +1,208 @@
1
1
  module MetricFu
2
-
3
- class Saikuro < Generator
4
-
5
-
6
- def emit
7
- relative_path = [File.dirname(__FILE__), '..', '..',
8
- 'vendor', 'saikuro', 'saikuro.rb']
9
- saikuro = File.expand_path(File.join(relative_path))
10
-
11
- format_directories
12
-
13
- options_string = MetricFu.saikuro.inject("") do |options, option|
14
- options + "--#{option.join(' ')} "
15
- end
16
-
17
- sh %{ruby "#{saikuro}" #{options_string}} do |ok, response|
18
- unless ok
19
- puts "Saikuro failed with exit status: #{response.exitstatus}"
20
- exit 1
2
+
3
+ class Saikuro < Generator
4
+
5
+ def emit
6
+ relative_path = [File.dirname(__FILE__), '..', '..',
7
+ 'vendor', 'saikuro', 'saikuro.rb']
8
+ saikuro = File.expand_path(File.join(relative_path))
9
+
10
+ MetricFu.saikuro[:input_directory] = format_directories
11
+
12
+ options_string = MetricFu.saikuro.inject("") do |options, option|
13
+ options + "--#{option.join(' ')} "
21
14
  end
22
- end
23
- end
24
-
25
- def format_directories
26
- dirs = MetricFu.saikuro[:input_directory].join(" | ")
27
- dirs = "\"#{dirs}\""
28
- MetricFu.saikuro[:input_directory] = dirs
29
- end
30
-
31
- def analyze
32
- @files = []
33
- saikuro_results.each do |path|
34
- if Saikuro::SFile.is_valid_text_file?(path)
35
- file = Saikuro::SFile.new(path)
36
- if file
37
- @files << file
15
+
16
+ sh %{ruby "#{saikuro}" #{options_string}} do |ok, response|
17
+ unless ok
18
+ puts "Saikuro failed with exit status: #{response.exitstatus}"
19
+ exit 1
38
20
  end
39
21
  end
40
22
  end
41
- @files = @files.sort_by do |file|
42
- file.elements.
43
- max {|a,b| a.complexity.to_i <=> b.complexity.to_i}.
44
- complexity.to_i
23
+
24
+ def format_directories
25
+ dirs = MetricFu.saikuro[:input_directory].join(" | ")
26
+ "\"#{dirs}\""
45
27
  end
46
- @files.reverse!
47
- klasses = []
48
- @files.each {|f| klasses << f.elements}
49
- klasses.flatten!
50
- @classes = klasses.sort_by {|k| k.complexity.to_i}
51
- @classes.reverse!
52
- meths = []
53
- @files.each {|f|
54
- f.elements.each {|el|
55
- el.defs.each {|defn|
56
- defn.name = "#{el.name}##{defn.name}"
57
- meths << defn}
28
+
29
+ def analyze
30
+ @files = []
31
+ saikuro_results.each do |path|
32
+ if Saikuro::SFile.is_valid_text_file?(path)
33
+ file = Saikuro::SFile.new(path)
34
+ if file
35
+ @files << file
36
+ end
37
+ end
38
+ end
39
+ @files = @files.sort_by do |file|
40
+ file.elements.
41
+ max {|a,b| a.complexity.to_i <=> b.complexity.to_i}.
42
+ complexity.to_i
43
+ end
44
+ @files.reverse!
45
+ klasses = []
46
+ @files.each {|f| klasses << f.elements}
47
+ klasses.flatten!
48
+ @classes = klasses.sort_by {|k| k.complexity.to_i}
49
+ @classes.reverse!
50
+ meths = []
51
+ @files.each {|f|
52
+ f.elements.each {|el|
53
+ el.defs.each {|defn|
54
+ defn.name = "#{el.name}##{defn.name}"
55
+ meths << defn}
56
+ }
58
57
  }
59
- }
60
- meths = meths.sort_by {|meth| meth.complexity.to_i}
61
- @meths = meths.reverse
62
-
63
- end
64
-
65
- def to_h
66
- files = @files.map do |file|
67
- my_file = file.to_h
68
- my_file[:filename] = file.filename
69
- my_file
58
+ meths = meths.sort_by {|meth| meth.complexity.to_i}
59
+ @meths = meths.reverse
70
60
  end
71
- {:saikuro => {:files => files,
72
- :classes => @classes.map {|c| c.to_h},
73
- :methods => @meths.map {|m| m.to_h}
74
- }
75
- }
76
- end
77
-
78
- def saikuro_results
79
- Dir.glob("#{metric_directory}/**/*.html")
80
- end
81
-
82
- private
83
-
84
-
85
- end
86
-
87
- class Saikuro::SFile
88
-
89
- attr_reader :elements
90
-
91
- def initialize(path)
92
- @path = path
93
- @file_handle = File.open(@path, "r")
94
- @elements = []
95
- get_elements
96
- end
97
-
98
- def self.is_valid_text_file?(path)
99
- File.open(path, "r") do |f|
100
- unless f.readline.match /--/
101
- return false
102
- else
103
- return true
61
+
62
+ def to_h
63
+ files = @files.map do |file|
64
+ my_file = file.to_h
65
+ my_file[:filename] = file.filename
66
+ my_file
104
67
  end
68
+ {:saikuro => {:files => files,
69
+ :classes => @classes.map {|c| c.to_h},
70
+ :methods => @meths.map {|m| m.to_h}
71
+ }
72
+ }
73
+ end
74
+
75
+ def saikuro_results
76
+ Dir.glob("#{metric_directory}/**/*.html")
105
77
  end
106
78
  end
107
-
108
- def filename
109
- File.basename(@path, '_cyclo.html')
110
- end
111
-
112
- def to_h
113
- merge_classes
114
- {:classes => @elements}
115
- end
116
-
117
- def get_elements
118
- begin
119
- while ( line = @file_handle.readline) do
120
- if line.match /START/
121
- line = @file_handle.readline
122
- element = Saikuro::ParsingElement.new(line)
123
- elsif line.match /END/
124
- @elements << element
125
- element = nil
79
+
80
+ class Saikuro::SFile
81
+
82
+ attr_reader :elements
83
+
84
+ def initialize(path)
85
+ @path = path
86
+ @file_handle = File.open(@path, "r")
87
+ @elements = []
88
+ get_elements
89
+ end
90
+
91
+ def self.is_valid_text_file?(path)
92
+ File.open(path, "r") do |f|
93
+ if f.eof? || !f.readline.match(/--/)
94
+ return false
126
95
  else
127
- element << line
96
+ return true
128
97
  end
129
98
  end
130
- rescue EOFError
131
- nil
132
99
  end
133
- end
134
-
135
-
136
- def merge_classes
137
- new_elements = []
138
- get_class_names.each do |target_class|
139
- elements = @elements.find_all {|el| el.name == target_class }
140
- complexity = 0
141
- lines = 0
142
- defns = []
143
- elements.each do |el|
144
- complexity += el.complexity.to_i
145
- lines += el.lines.to_i
146
- defns << el.defs
100
+
101
+ def filename
102
+ File.basename(@path, '_cyclo.html')
103
+ end
104
+
105
+ def to_h
106
+ merge_classes
107
+ {:classes => @elements}
108
+ end
109
+
110
+ def get_elements
111
+ begin
112
+ while (line = @file_handle.readline) do
113
+ return [] if line.nil? || line !~ /\S/
114
+ element ||= nil
115
+ if line.match /START/
116
+ unless element.nil?
117
+ @elements << element
118
+ element = nil
119
+ end
120
+ line = @file_handle.readline
121
+ element = Saikuro::ParsingElement.new(line)
122
+ elsif line.match /END/
123
+ @elements << element unless element.nil?
124
+ element = nil
125
+ else
126
+ element << line
127
+ end
128
+ end
129
+ rescue EOFError
130
+ nil
147
131
  end
148
-
149
- new_element = {:class_name => target_class,
150
- :complexity => complexity,
151
- :lines => lines,
152
- :methods => defns.flatten.map {|d| d.to_h}}
153
- new_element[:methods] = new_element[:methods].
154
- sort_by {|x| x[:complexity] }.
155
- reverse
156
-
157
- new_elements << new_element
158
132
  end
159
- @elements = new_elements if new_elements
160
- end
161
-
162
- def get_class_names
163
- class_names = []
164
- @elements.each do |element|
165
- unless class_names.include?(element.name)
166
- class_names << element.name
133
+
134
+
135
+ def merge_classes
136
+ new_elements = []
137
+ get_class_names.each do |target_class|
138
+ elements = @elements.find_all {|el| el.name == target_class }
139
+ complexity = 0
140
+ lines = 0
141
+ defns = []
142
+ elements.each do |el|
143
+ complexity += el.complexity.to_i
144
+ lines += el.lines.to_i
145
+ defns << el.defs
146
+ end
147
+
148
+ new_element = {:class_name => target_class,
149
+ :complexity => complexity,
150
+ :lines => lines,
151
+ :methods => defns.flatten.map {|d| d.to_h}}
152
+ new_element[:methods] = new_element[:methods].
153
+ sort_by {|x| x[:complexity] }.
154
+ reverse
155
+
156
+ new_elements << new_element
167
157
  end
158
+ @elements = new_elements if new_elements
168
159
  end
169
- class_names
170
- end
171
-
172
- end
173
-
174
- class Saikuro::ParsingElement
175
- TYPE_REGEX=/Type:(.*) Name/
176
- NAME_REGEX=/Name:(.*) Complexity/
177
- COMPLEXITY_REGEX=/Complexity:(.*) Lines/
178
- LINES_REGEX=/Lines:(.*)/
179
-
180
- attr_reader :complexity, :lines, :defs, :element_type
181
- attr_accessor :name
182
-
183
- def initialize(line)
184
- @line = line
185
- @element_type = line.match(TYPE_REGEX)[1].strip
186
- @name = line.match(NAME_REGEX)[1].strip
187
- @complexity = line.match(COMPLEXITY_REGEX)[1].strip
188
- @lines = line.match(LINES_REGEX)[1].strip
189
- @defs = []
190
- end
191
-
192
- def <<(line)
193
- @defs << Saikuro::ParsingElement.new(line)
160
+
161
+ def get_class_names
162
+ class_names = []
163
+ @elements.each do |element|
164
+ unless class_names.include?(element.name)
165
+ class_names << element.name
166
+ end
167
+ end
168
+ class_names
169
+ end
170
+
194
171
  end
195
-
196
- def to_h
197
- base = {:name => @name, :complexity => @complexity.to_i, :lines => @lines.to_i}
198
- unless @defs.empty?
199
- defs = @defs.map do |my_def|
200
- my_def = my_def.to_h
201
- my_def.delete(:defs)
202
- my_def
172
+
173
+ class Saikuro::ParsingElement
174
+ TYPE_REGEX=/Type:(.*) Name/
175
+ NAME_REGEX=/Name:(.*) Complexity/
176
+ COMPLEXITY_REGEX=/Complexity:(.*) Lines/
177
+ LINES_REGEX=/Lines:(.*)/
178
+
179
+ attr_reader :complexity, :lines, :defs, :element_type
180
+ attr_accessor :name
181
+
182
+ def initialize(line)
183
+ @line = line
184
+ @element_type = line.match(TYPE_REGEX)[1].strip
185
+ @name = line.match(NAME_REGEX)[1].strip
186
+ @complexity = line.match(COMPLEXITY_REGEX)[1].strip
187
+ @lines = line.match(LINES_REGEX)[1].strip
188
+ @defs = []
189
+ end
190
+
191
+ def <<(line)
192
+ @defs << Saikuro::ParsingElement.new(line)
193
+ end
194
+
195
+ def to_h
196
+ base = {:name => @name, :complexity => @complexity.to_i, :lines => @lines.to_i}
197
+ unless @defs.empty?
198
+ defs = @defs.map do |my_def|
199
+ my_def = my_def.to_h
200
+ my_def.delete(:defs)
201
+ my_def
202
+ end
203
+ base[:defs] = defs
203
204
  end
204
- base[:defs] = defs
205
+ return base
205
206
  end
206
- return base
207
207
  end
208
208
  end
209
-
210
-
211
- end