jscruggs-metric_fu 1.0.2 → 1.1.0

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