fukuzatsu 1.0.6 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/README.md +11 -9
  4. data/doc/images/details.png +0 -0
  5. data/doc/images/overview.png +0 -0
  6. data/fukuzatsu.gemspec +5 -2
  7. data/lib/fukuzatsu.rb +18 -4
  8. data/lib/fukuzatsu/cli.rb +2 -15
  9. data/lib/fukuzatsu/file_reader.rb +38 -0
  10. data/lib/fukuzatsu/formatters/base.rb +61 -22
  11. data/lib/fukuzatsu/formatters/csv.rb +28 -29
  12. data/lib/fukuzatsu/formatters/html.rb +61 -66
  13. data/lib/fukuzatsu/formatters/html_index.rb +40 -33
  14. data/lib/fukuzatsu/formatters/json.rb +37 -0
  15. data/lib/fukuzatsu/formatters/json_index.rb +31 -0
  16. data/lib/fukuzatsu/formatters/templates/index.html.haml +21 -32
  17. data/lib/fukuzatsu/formatters/templates/output.html.haml +19 -50
  18. data/lib/fukuzatsu/formatters/text.rb +53 -41
  19. data/lib/fukuzatsu/parser.rb +31 -49
  20. data/lib/fukuzatsu/summary.rb +101 -0
  21. data/lib/fukuzatsu/version.rb +1 -1
  22. data/spec/cli_spec.rb +7 -40
  23. data/spec/fixtures/class.rb +30 -0
  24. data/spec/fixtures/module.rb +12 -0
  25. data/spec/fixtures/procedural.rb +8 -0
  26. data/spec/formatters/csv_spec.rb +43 -21
  27. data/spec/formatters/html_spec.rb +38 -19
  28. data/spec/formatters/json_spec.rb +81 -0
  29. data/spec/formatters/text_spec.rb +18 -18
  30. data/spec/parser_spec.rb +39 -0
  31. data/spec/summary_spec.rb +28 -0
  32. metadata +51 -43
  33. data/doc/details.png +0 -0
  34. data/doc/overview.png +0 -0
  35. data/lib/fukuzatsu/analyzer.rb +0 -162
  36. data/lib/fukuzatsu/line_of_code.rb +0 -19
  37. data/lib/fukuzatsu/parsed_file.rb +0 -89
  38. data/lib/fukuzatsu/parsed_method.rb +0 -32
  39. data/spec/analyzer_spec.rb +0 -122
  40. data/spec/fixtures/eg_class.rb +0 -8
  41. data/spec/fixtures/eg_mod_class.rb +0 -2
  42. data/spec/fixtures/eg_mod_class_2.rb +0 -5
  43. data/spec/fixtures/eg_module.rb +0 -2
  44. data/spec/fixtures/module_with_class.rb +0 -9
  45. data/spec/fixtures/multiple_methods.rb +0 -7
  46. data/spec/fixtures/nested_methods.rb +0 -8
  47. data/spec/fixtures/program_1.rb +0 -19
  48. data/spec/fixtures/program_2.rb +0 -25
  49. data/spec/fixtures/program_3.rb +0 -66
  50. data/spec/fixtures/program_4.rb +0 -1
  51. data/spec/fixtures/single_class.rb +0 -9
  52. data/spec/fixtures/single_method.rb +0 -3
  53. data/spec/formatters/html_index_spec.rb +0 -36
  54. data/spec/parsed_file_spec.rb +0 -67
  55. data/spec/parsed_method_spec.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60581ee307ba16c4cbc28ce085523b9eb8b2ab04
4
- data.tar.gz: 29a01ba5038f7470b3041dee614fc41ae0427fc8
3
+ metadata.gz: 2f07664e5fec8ebb4806db7425780356672dbff2
4
+ data.tar.gz: d53ab4e6300ee913f663ab334cb71599a89a7d7b
5
5
  SHA512:
6
- metadata.gz: 67cd3b33423fe20e3d76970ff0b6e94fb366f39d190b0f9e4d6624e967102591cc9ca89dfff9ea7df2f3dc71ece3a9ef835c5c2bc939bc099c9cffe7e75d6fc7
7
- data.tar.gz: b9d7dca96fba0c396c547043796f6778a7da9f5fb182caf8d57bce1d9d29cc7e41812aa9918b8ed0c4c0f9c7da780f01a7ca98df922d2a2a33e438546784bfcf
6
+ metadata.gz: 32d568e9018a733ea7e9a3b98c3df9cabad1917aa5ce0d2ba96f2ade60d7f65677afae5939ffaa80db506aa8bff44b827f3407d3b160df05e050fdfde69c411f
7
+ data.tar.gz: 097cbc999cd38da8c69eab575c8143754f1498b97a5f6b861682b6d2057be2531ff9114f4dd7e756526d37517a0a0b5c54d601fb583b8d9ff5c55e030fdc83b1
data/.gitignore CHANGED
@@ -7,7 +7,7 @@ Gemfile.lock
7
7
  InstalledFiles
8
8
  _yardoc
9
9
  coverage
10
- doc/*/
10
+ doc/fukuzatsu/*
11
11
  lib/bundler/man
12
12
  pkg
13
13
  rdoc
data/README.md CHANGED
@@ -1,23 +1,22 @@
1
1
  # Fukuzatsu
2
2
 
3
3
  Fukuzatsu ("complexity") is a tool for measuring code complexity in Ruby class files. Its analysis
4
- generates relative complexity figures similar to the results of cyclomatic complexity algorithms.
5
- (You can learn more about cyclomatic complexity at http://en.wikipedia.org/wiki/Cyclomatic_complexity)
4
+ generates scores based on cyclomatic complexity algorithms, which in simplest terms measure the number of execution paths through a given piece of code. (You can learn more about cyclomatic complexity [here](http://en.wikipedia.org/wiki/Cyclomatic_complexity).)
6
5
 
7
6
  Why should you care about this kind of complexity? More complex code tends to attract bugs and to
8
7
  increase the friction around extending features or refactoring code.
9
8
 
10
- Fukuzatsu was created by [Coraline Ada Ehmke](http://where.coraline.codes/) with invaluable assistance from [Mike Ziwisky](https://github.com/mziwisky). It was inspired by Saikuro, written by Zev Blut.
9
+ Fukuzatsu was created by [Coraline Ada Ehmke](http://where.coraline.codes/) and is maintained by [Coraline Ada Ehmke](http://where.coraline.codes/), [Mike Ziwisky](https://github.com/mziwisky), and the team at [Instructure](http://www.instructure.com/). It was originally inspired by Saikuro, written by Zev Blut.
11
10
 
12
11
  ## Screenshots
13
12
 
14
13
  These are screenshots of the `-f html` output. First, the overall project summary:
15
14
 
16
- ![Project Summary](https://gitlab.com/coraline/fukuzatsu/raw/master/doc/overview.png)
15
+ ![Project Summary](https://gitlab.com/coraline/fukuzatsu/raw/master/doc/images/overview.png)
17
16
 
18
17
  Then the detail view of a single class:
19
18
 
20
- ![Project Summary](https://gitlab.com/coraline/fukuzatsu/raw/master/doc/details.png)
19
+ ![Project Summary](https://gitlab.com/coraline/fukuzatsu/raw/master/doc/images/details.png)
21
20
 
22
21
  ## Installation
23
22
 
@@ -32,17 +31,20 @@ This installs the CLI tool.
32
31
  fuku check path/to/file/my_file.rb
33
32
 
34
33
  fuku check path/to/file/my_file.rb -f html
35
- # Writes to doc/fuzuzatsu/path/to_file/my_file.rb.htm
34
+ # Writes to doc/fuzuzatsu/htm/index.htm
36
35
 
37
36
  fuku check path/to/file/my_file.rb -f csv
38
- # Writes to doc/fuzuzatsu/path/to_file/my_file.rb.csv
37
+ # Writes to doc/fuzuzatsu/csv/results.csv
38
+
39
+ fuku check path/to/file/my_file.rb -f json
40
+ # Writes to doc/fuzuzatsu/json/results.json
39
41
 
40
42
  ## Contributing
41
43
 
42
- Please note that this project is released with a [Contributor Code of Conduct](https://gitlab.com/coraline/fukuzatsu/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
44
+ Please note that this project is released with a [Contributor Code of Conduct](http://contributor-covenant.org/version/1/0/0/). By participating in this project you agree to abide by its terms.
43
45
 
44
46
  1. Fork it
45
47
  2. Create your feature branch (`git checkout -b my-new-feature`)
46
48
  3. Commit your changes (`git commit -am 'Add some feature'`)
47
49
  4. Push to the branch (`git push origin my-new-feature`)
48
- 5. Create a new Pull Request
50
+ 5. Create a new Pull Request
Binary file
Binary file
@@ -6,8 +6,8 @@ require 'fukuzatsu/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "fukuzatsu"
8
8
  spec.version = Fukuzatsu::VERSION
9
- spec.authors = ["Bantik"]
10
- spec.email = ["coraline@idolhands.com"]
9
+ spec.authors = ["Coraline Ada Ehmke", "Mike Ziwisky"]
10
+ spec.email = ["coraline@idolhands.com", "mikezx@gmail.com"]
11
11
  spec.summary = "A simple code complexity analyzer."
12
12
  spec.description = "Calculates code complexity as a measure of paths through code execution. CI integration and beautiful output options."
13
13
  spec.homepage = "https://gitlab.com/coraline/fukuzatsu/tree/master"
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "analyst", ">= 0.16.0"
21
22
  spec.add_dependency "ephemeral"
22
23
  spec.add_dependency "poro_plus"
23
24
  spec.add_dependency "haml"
@@ -29,7 +30,9 @@ Gem::Specification.new do |spec|
29
30
 
30
31
  spec.add_development_dependency "bundler", "~> 1.6"
31
32
  spec.add_development_dependency "rake"
33
+ spec.add_development_dependency "pry"
32
34
  spec.add_development_dependency "rspec"
33
35
  spec.add_development_dependency "simplecov"
34
36
 
35
37
  end
38
+
@@ -2,19 +2,33 @@ require 'ephemeral'
2
2
  require 'poro_plus'
3
3
  require 'fileutils'
4
4
  require 'haml'
5
+ require 'analyst'
6
+ require 'pry'
5
7
 
6
- require_relative "fukuzatsu/analyzer"
7
8
  require_relative "fukuzatsu/cli"
9
+ require_relative "fukuzatsu/file_reader"
8
10
  require_relative "fukuzatsu/formatters/base"
9
11
  require_relative "fukuzatsu/formatters/csv"
10
12
  require_relative "fukuzatsu/formatters/html"
11
13
  require_relative "fukuzatsu/formatters/html_index"
14
+ require_relative "fukuzatsu/formatters/json"
15
+ require_relative "fukuzatsu/formatters/json_index"
12
16
  require_relative "fukuzatsu/formatters/text"
13
- require_relative "fukuzatsu/line_of_code"
14
- require_relative "fukuzatsu/parsed_file"
15
- require_relative "fukuzatsu/parsed_method"
16
17
  require_relative "fukuzatsu/parser"
18
+ require_relative "fukuzatsu/summary"
17
19
  require_relative "fukuzatsu/version"
18
20
 
19
21
  module Fukuzatsu
22
+ def self.new(path_to_files, formatter=:text, threshold=0)
23
+ Fukuzatsu::Parser.new(path_to_files, formatters[formatter], threshold)
24
+ end
25
+
26
+ def self.formatters
27
+ {
28
+ html: Fukuzatsu::Formatters::Html,
29
+ csv: Fukuzatsu::Formatters::Csv,
30
+ json: Fukuzatsu::Formatters::Json,
31
+ text: Fukuzatsu::Formatters::Text
32
+ }
33
+ end
20
34
  end
@@ -13,13 +13,7 @@ module Fukuzatsu
13
13
  method_option :threshold, :type => :numeric, :default => 0, :aliases => "-t"
14
14
 
15
15
  def check(path="./")
16
- parser = Fukuzatsu::Parser.new(
17
- path,
18
- formatter,
19
- options['threshold']
20
- )
21
- parser.parse_files
22
- parser.report
16
+ Fukuzatsu.new(path, formatter, options['threshold']).report
23
17
  end
24
18
 
25
19
  default_task :check
@@ -27,14 +21,7 @@ module Fukuzatsu
27
21
  private
28
22
 
29
23
  def formatter
30
- case options['format']
31
- when 'html'
32
- Formatters::Html
33
- when 'csv'
34
- Formatters::Csv
35
- else
36
- Formatters::Text
37
- end
24
+ options['format'] && options['format'].to_sym || :text
38
25
  end
39
26
 
40
27
  end
@@ -0,0 +1,38 @@
1
+ module Fukuzatsu
2
+ class FileReader
3
+
4
+ attr_reader :path_to_files
5
+
6
+ def initialize(path_to_files)
7
+ @path_to_files = path_to_files
8
+ end
9
+
10
+ def source_files
11
+ file_list.map{ |file_path| SourceFile.new(file_path) }
12
+ end
13
+
14
+ private
15
+
16
+ def file_list
17
+ if File.directory?(path_to_files)
18
+ return Dir.glob(File.join(path_to_files, "**", "*.rb"))
19
+ else
20
+ return [path_to_files]
21
+ end
22
+ end
23
+
24
+ class SourceFile
25
+ attr_reader :file
26
+ def initialize(file)
27
+ @file = File.open(file, "r")
28
+ end
29
+ def filename
30
+ file.path
31
+ end
32
+ def contents
33
+ self.file.read
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -1,31 +1,70 @@
1
- module Formatters
1
+ module Fukuzatsu
2
2
 
3
- module Base
3
+ module Formatters
4
4
 
5
- def self.included(klass)
6
- klass.send(:attr_accessor, :file)
7
- klass.send(:attr_accessor, :source)
8
- klass.send(:attr_accessor, :output_directory)
9
- end
5
+ module Base
10
6
 
11
- def initialize(file, output_directory=nil, source="")
12
- self.file = file
13
- self.source = source
14
- self.output_directory = output_directory
15
- end
7
+ BASE_OUTPUT_DIRECTORY = "doc/fukuzatsu/"
16
8
 
17
- def filename
18
- File.basename(self.file.path_to_file) + file_extension
19
- end
9
+ def self.included(klass)
10
+ klass.send(:attr_accessor, :summary)
11
+ klass.send(:attr_accessor, :source)
12
+ klass.extend(ClassMethods)
13
+ end
20
14
 
21
- def output_path
22
- output_path = File.dirname(File.join(self.output_directory, self.file.path_to_file))
23
- FileUtils.mkpath(output_path)
24
- output_path
25
- end
15
+ def initialize(source: nil, summary:nil)
16
+ self.source = source
17
+ self.summary = summary
18
+ end
19
+
20
+ def export
21
+ begin
22
+ File.open(path_to_results, 'w') {|outfile| outfile.write(content)}
23
+ rescue Exception => e
24
+ puts "Unable to write output: #{e} #{e.backtrace}"
25
+ end
26
+ end
27
+
28
+ def filename
29
+ File.basename(self.summary.source_file) + file_extension
30
+ end
31
+
32
+ def output_directory
33
+ BASE_OUTPUT_DIRECTORY + file_extension.gsub(".","")
34
+ end
35
+
36
+ def output_path
37
+ if self.summary
38
+ output_path = output_directory + "/" + File.dirname(self.summary.source_file)
39
+ FileUtils.mkpath(output_path)
40
+ else
41
+ output_path = File.dirname(output_directory)
42
+ end
43
+ output_path
44
+ end
45
+
46
+ def path_to_results
47
+ File.join(output_path, filename)
48
+ end
49
+
50
+ module ClassMethods
51
+
52
+ def index(summaries)
53
+ end
54
+
55
+ def reset_output_directory
56
+ directory = new.output_directory
57
+ begin
58
+ FileUtils.remove_dir(directory)
59
+ rescue Errno::ENOENT
60
+ end
61
+ FileUtils.mkpath(directory)
62
+ end
26
63
 
27
- def path_to_results
28
- File.join(output_path, filename)
64
+ def explain(count)
65
+ puts "Processed #{count} file(s). Results written to #{new.output_directory}."
66
+ end
67
+ end
29
68
  end
30
69
 
31
70
  end
@@ -1,43 +1,42 @@
1
- module Formatters
1
+ module Fukuzatsu
2
2
 
3
- class Csv
3
+ module Formatters
4
4
 
5
- include Formatters::Base
5
+ class Csv
6
6
 
7
- def self.has_index?
8
- false
9
- end
7
+ include Formatters::Base
10
8
 
11
- def self.writes_to_file_system?
12
- true
13
- end
9
+ def self.writes_to_file_system?
10
+ true
11
+ end
14
12
 
15
- def content
16
- rows + "\r\n"
17
- end
13
+ def content
14
+ rows + "\r\n"
15
+ end
18
16
 
19
- def export
20
- begin
21
- File.open(path_to_results, 'a') {|outfile| outfile.write(content)}
22
- rescue Exception => e
23
- puts "Unable to write output: #{e} #{e.backtrace}"
17
+ def export
18
+ begin
19
+ File.open(path_to_results, 'a') {|outfile| outfile.write(content)}
20
+ rescue Exception => e
21
+ puts "Unable to write output: #{e} #{e.backtrace}"
22
+ end
24
23
  end
25
- end
26
24
 
27
- def file_extension
28
- ".csv"
29
- end
25
+ def file_extension
26
+ ".csv"
27
+ end
30
28
 
31
- def path_to_results
32
- File.join(output_directory, "results#{file_extension}")
33
- end
29
+ def path_to_results
30
+ File.join(output_directory, "results#{file_extension}")
31
+ end
32
+
33
+ def rows
34
+ summary.summaries.map do |summary|
35
+ "#{summary.source_file},#{summary.container_name},#{summary.entity_name},#{summary.complexity}"
36
+ end.join("\r\n")
37
+ end
34
38
 
35
- def rows
36
- file.methods.map do |method|
37
- "#{file.path_to_file},#{file.class_name},#{method.name},#{method.complexity}"
38
- end.join("\r\n")
39
39
  end
40
40
 
41
41
  end
42
-
43
42
  end
@@ -1,87 +1,82 @@
1
1
  require 'rouge'
2
2
 
3
- module Formatters
3
+ module Fukuzatsu
4
4
 
5
- class Html
5
+ module Formatters
6
6
 
7
- include Formatters::Base
7
+ class Html
8
8
 
9
- def self.has_index?
10
- true
11
- end
9
+ include Formatters::Base
12
10
 
13
- def self.writes_to_file_system?
14
- true
15
- end
11
+ def self.index(summaries)
12
+ Fukuzatsu::Formatters::HtmlIndex.new(summaries).export
13
+ end
16
14
 
17
- def self.index_class
18
- Formatters::HtmlIndex
19
- end
15
+ def columns
16
+ ["class", "method", "complexity"]
17
+ end
20
18
 
21
- def columns
22
- ["class", "method", "complexity"]
23
- end
19
+ def content
20
+ Haml::Engine.new(output_template).render(
21
+ Object.new, {
22
+ header: header,
23
+ rows: rows,
24
+ source_lines: preprocessed,
25
+ class_name: summary.container_name,
26
+ average_complexity: sprintf("%0.2f", summary.average_complexity),
27
+ path_to_file: summary.source_file,
28
+ date: Time.now.strftime("%Y/%m/%d"),
29
+ time: Time.now.strftime("%l:%M %P")
30
+ }
31
+ )
32
+ end
24
33
 
25
- def content
26
- Haml::Engine.new(output_template).render(
27
- Object.new, {
28
- header: header,
29
- rows: rows,
30
- source_lines: preprocessed,
31
- class_name: file.class_name,
32
- complexity: file.complexity,
33
- path_to_file: file.path_to_file,
34
- date: Time.now.strftime("%Y/%m/%d"),
35
- time: Time.now.strftime("%l:%M %P")
36
- }
37
- )
38
- end
34
+ def export
35
+ begin
36
+ File.open(path_to_results, 'w') {|outfile| outfile.write(content)}
37
+ rescue Exception => e
38
+ puts "Unable to write output: #{e} #{e.backtrace}"
39
+ end
40
+ end
39
41
 
40
- def export
41
- begin
42
- File.open(path_to_results, 'w') {|outfile| outfile.write(content)}
43
- rescue Exception => e
44
- puts "Unable to write output: #{e} #{e.backtrace}"
42
+ def file_extension
43
+ ".htm"
45
44
  end
46
- end
47
45
 
48
- def formatter
49
- Rouge::Formatters::HTML.new(line_numbers: true)
50
- end
46
+ def formatter
47
+ Rouge::Formatters::HTML.new(line_numbers: true)
48
+ end
51
49
 
52
- def header
53
- columns.map{|col| "<th>#{col.titleize}</th>"}.join("\r\n")
54
- end
50
+ def header
51
+ columns.map{|col| "<th>#{col.titleize}</th>"}.join("\r\n")
52
+ end
55
53
 
56
- def lexer
57
- lexer = Rouge::Lexers::Ruby.new
58
- end
54
+ def lexer
55
+ lexer = Rouge::Lexers::Ruby.new
56
+ end
59
57
 
60
- def output_template
61
- File.read(File.dirname(__FILE__) + "/templates/output.html.haml")
62
- end
58
+ def output_template
59
+ File.read(File.dirname(__FILE__) + "/templates/output.html.haml")
60
+ end
63
61
 
64
- def preprocessed
65
- formatter.format(lexer.lex(source))
66
- end
62
+ def preprocessed
63
+ formatter.format(lexer.lex(summary.raw_source))
64
+ end
67
65
 
68
- def rows
69
- i = 0
70
- file.methods.inject([]) do |a, method|
71
- i += 1
72
- a << "<tr class='#{i % 2 == 1 ? 'even' : 'odd'}'>"
73
- a << " <td>#{file.class_name}</td>"
74
- a << " <td>#{method.name}</td>"
75
- a << " <td>#{method.complexity}</td>"
76
- a << "</tr>"
77
- a
78
- end.join("\r\n")
79
- end
66
+ def rows
67
+ i = 0
68
+ summary.summaries.inject([]) do |a, summary|
69
+ i += 1
70
+ a << "<tr class='#{i % 2 == 1 ? 'even' : 'odd'}'>"
71
+ a << " <td>#{summary.container_name}</td>"
72
+ a << " <td>#{summary.entity_name}</td>"
73
+ a << " <td>#{summary.complexity}</td>"
74
+ a << "</tr>"
75
+ a
76
+ end.join("\r\n")
77
+ end
80
78
 
81
- def file_extension
82
- ".htm"
83
79
  end
84
80
 
85
81
  end
86
-
87
- end
82
+ end