fukuzatsu 1.0.6 → 2.1.1

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 (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