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
@@ -1,25 +1,16 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Formatters::Text" do
3
+ describe Fukuzatsu::Formatters::Text do
4
4
 
5
- let (:parsed_file) { ParsedFile.new(class_name: "Foo", complexity: 11) }
6
- let (:method_1) { ParsedMethod.new(
7
- name: "initialize",
8
- complexity: 13,
9
- type: "instance"
5
+ let (:summary) { Fukuzatsu::Summary.new(
6
+ :source => "foo.rb",
7
+ :entity => "Foo",
8
+ :container => "Foo",
9
+ :summaries => []
10
10
  )
11
11
  }
12
- let (:method_2) { ParsedMethod.new(
13
- name: "report",
14
- complexity: 11,
15
- type: "instance"
16
- )
17
- }
18
-
19
12
 
20
- let(:parsed_file) { Struct.new(:path_to_file, :class_name, :average_complexity)}
21
- let(:mock_parsed_file) { parsed_file.new("fred/foo.rb", "Foo", 12) }
22
- let (:formatter) { Formatters::Text.new(mock_parsed_file) }
13
+ let (:formatter) { Fukuzatsu::Formatters::Text.new(summary: summary) }
23
14
 
24
15
  describe "#header" do
25
16
  it "returns a header array" do
@@ -28,10 +19,19 @@ describe "Formatters::Text" do
28
19
  end
29
20
 
30
21
  describe "#rows" do
22
+
23
+ before do
24
+ allow(summary).to receive(:container_name).and_return("Foo")
25
+ allow(summary).to receive(:entity_name).and_return("*")
26
+ allow(summary).to receive(:complexity).and_return(13)
27
+ allow(summary).to receive(:averge_complexity).and_return(11)
28
+ end
29
+
31
30
  it "returns formatted rows" do
32
- allow(mock_parsed_file).to receive(:methods) { [method_1, method_2] }
33
31
  expect(formatter.rows).to eq(
34
- [["\e[31mFoo\e[0m", "\e[31m*initialize\e[0m", "\e[31m13\e[0m"], ["\e[33mFoo\e[0m", "\e[33m*report\e[0m", "\e[33m11\e[0m"]]
32
+ [
33
+ ["\e[31mFoo\e[0m", "\e[31m*\e[0m", "\e[31m13\e[0m"]
34
+ ]
35
35
  )
36
36
  end
37
37
  end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fukuzatsu::Parser do
4
+
5
+ let(:parser) { Fukuzatsu::Parser.new(
6
+ "./fixtures/",
7
+ "formatter proxy",
8
+ 14
9
+ )
10
+ }
11
+
12
+ describe "#initialize" do
13
+ it "initializes its path to files" do
14
+ expect(parser.path_to_files).to eq "./fixtures/"
15
+ end
16
+ end
17
+
18
+ describe "check_complexity" do
19
+ it "returns if no threshold is set" do
20
+ allow(parser).to receive(:threshold) { 0 }
21
+ expect(parser.send(:check_complexity)).to be_nil
22
+ end
23
+ it "returns if threshold is not exceeded" do
24
+ allow(parser).to receive(:threshold) { 5 }
25
+ allow(parser).to receive(:average_complexities) { [1,2,3,4,5] }
26
+ expect(parser.send(:check_complexity)).to be_nil
27
+ end
28
+ it "returns an exit code if threshold exceeded" do
29
+ allow(parser).to receive(:threshold) { 5 }
30
+ allow(parser).to receive(:average_complexities) { [1,2,3,4,5,6] }
31
+ begin
32
+ parser.send(:check_complexity)
33
+ rescue SystemExit => e
34
+ expect(e.message).to eq("exit")
35
+ end
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fukuzatsu::Summary do
4
+
5
+ describe "#complexity" do
6
+
7
+ let(:class_source) { File.open("./spec/fixtures/class.rb", "r").readlines }
8
+ let(:class_complexity) { class_source.first.split('complexity:')[1].to_i }
9
+
10
+ let(:module_source) { File.open("./spec/fixtures/module.rb", "r").readlines }
11
+ let(:module_complexity) { module_source.first.split('complexity:')[1].to_i }
12
+
13
+ let(:procedural_source) { File.open("./spec/fixtures/procedural.rb", "r").readlines }
14
+ let(:procedural_complexity) { procedural_source.first.split('complexity:')[1].to_i }
15
+
16
+ it "calculates complexity of a class" do
17
+ summary = Fukuzatsu::Summary.from(content: class_source.join("\n")).first
18
+ expect(summary.complexity).to eq(class_complexity)
19
+ end
20
+
21
+ it "calculates complexity of a module" do
22
+ summary = Fukuzatsu::Summary.from(content: module_source.join("\n")).first
23
+ expect(summary.complexity).to eq(module_complexity)
24
+ end
25
+
26
+ end
27
+
28
+ end
metadata CHANGED
@@ -1,15 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fukuzatsu
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
- - Bantik
7
+ - Coraline Ada Ehmke
8
+ - Mike Ziwisky
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-10-22 00:00:00.000000000 Z
12
+ date: 2014-11-26 00:00:00.000000000 Z
12
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: analyst
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 0.16.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: 0.16.0
13
28
  - !ruby/object:Gem::Dependency
14
29
  name: ephemeral
15
30
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +165,20 @@ dependencies:
150
165
  - - ">="
151
166
  - !ruby/object:Gem::Version
152
167
  version: '0'
168
+ - !ruby/object:Gem::Dependency
169
+ name: pry
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ type: :development
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
153
182
  - !ruby/object:Gem::Dependency
154
183
  name: rspec
155
184
  requirement: !ruby/object:Gem::Requirement
@@ -182,6 +211,7 @@ description: Calculates code complexity as a measure of paths through code execu
182
211
  CI integration and beautiful output options.
183
212
  email:
184
213
  - coraline@idolhands.com
214
+ - mikezx@gmail.com
185
215
  executables:
186
216
  - fuku
187
217
  extensions: []
@@ -195,46 +225,35 @@ files:
195
225
  - README.md
196
226
  - Rakefile
197
227
  - bin/fuku
198
- - doc/details.png
199
- - doc/overview.png
228
+ - doc/images/details.png
229
+ - doc/images/overview.png
200
230
  - fukuzatsu.gemspec
201
231
  - lib/fukuzatsu.rb
202
- - lib/fukuzatsu/analyzer.rb
203
232
  - lib/fukuzatsu/cli.rb
233
+ - lib/fukuzatsu/file_reader.rb
204
234
  - lib/fukuzatsu/formatters/base.rb
205
235
  - lib/fukuzatsu/formatters/csv.rb
206
236
  - lib/fukuzatsu/formatters/html.rb
207
237
  - lib/fukuzatsu/formatters/html_index.rb
238
+ - lib/fukuzatsu/formatters/json.rb
239
+ - lib/fukuzatsu/formatters/json_index.rb
208
240
  - lib/fukuzatsu/formatters/templates/index.html.haml
209
241
  - lib/fukuzatsu/formatters/templates/output.html.haml
210
242
  - lib/fukuzatsu/formatters/text.rb
211
- - lib/fukuzatsu/line_of_code.rb
212
- - lib/fukuzatsu/parsed_file.rb
213
- - lib/fukuzatsu/parsed_method.rb
214
243
  - lib/fukuzatsu/parser.rb
244
+ - lib/fukuzatsu/summary.rb
215
245
  - lib/fukuzatsu/version.rb
216
- - spec/analyzer_spec.rb
217
246
  - spec/cli_spec.rb
218
- - spec/fixtures/eg_class.rb
219
- - spec/fixtures/eg_mod_class.rb
220
- - spec/fixtures/eg_mod_class_2.rb
221
- - spec/fixtures/eg_module.rb
222
- - spec/fixtures/module_with_class.rb
223
- - spec/fixtures/multiple_methods.rb
224
- - spec/fixtures/nested_methods.rb
225
- - spec/fixtures/program_1.rb
226
- - spec/fixtures/program_2.rb
227
- - spec/fixtures/program_3.rb
228
- - spec/fixtures/program_4.rb
229
- - spec/fixtures/single_class.rb
230
- - spec/fixtures/single_method.rb
247
+ - spec/fixtures/class.rb
248
+ - spec/fixtures/module.rb
249
+ - spec/fixtures/procedural.rb
231
250
  - spec/formatters/csv_spec.rb
232
- - spec/formatters/html_index_spec.rb
233
251
  - spec/formatters/html_spec.rb
252
+ - spec/formatters/json_spec.rb
234
253
  - spec/formatters/text_spec.rb
235
- - spec/parsed_file_spec.rb
236
- - spec/parsed_method_spec.rb
254
+ - spec/parser_spec.rb
237
255
  - spec/spec_helper.rb
256
+ - spec/summary_spec.rb
238
257
  - tags
239
258
  homepage: https://gitlab.com/coraline/fukuzatsu/tree/master
240
259
  licenses:
@@ -261,26 +280,15 @@ signing_key:
261
280
  specification_version: 4
262
281
  summary: A simple code complexity analyzer.
263
282
  test_files:
264
- - spec/analyzer_spec.rb
265
283
  - spec/cli_spec.rb
266
- - spec/fixtures/eg_class.rb
267
- - spec/fixtures/eg_mod_class.rb
268
- - spec/fixtures/eg_mod_class_2.rb
269
- - spec/fixtures/eg_module.rb
270
- - spec/fixtures/module_with_class.rb
271
- - spec/fixtures/multiple_methods.rb
272
- - spec/fixtures/nested_methods.rb
273
- - spec/fixtures/program_1.rb
274
- - spec/fixtures/program_2.rb
275
- - spec/fixtures/program_3.rb
276
- - spec/fixtures/program_4.rb
277
- - spec/fixtures/single_class.rb
278
- - spec/fixtures/single_method.rb
284
+ - spec/fixtures/class.rb
285
+ - spec/fixtures/module.rb
286
+ - spec/fixtures/procedural.rb
279
287
  - spec/formatters/csv_spec.rb
280
- - spec/formatters/html_index_spec.rb
281
288
  - spec/formatters/html_spec.rb
289
+ - spec/formatters/json_spec.rb
282
290
  - spec/formatters/text_spec.rb
283
- - spec/parsed_file_spec.rb
284
- - spec/parsed_method_spec.rb
291
+ - spec/parser_spec.rb
285
292
  - spec/spec_helper.rb
293
+ - spec/summary_spec.rb
286
294
  has_rdoc:
Binary file
Binary file
@@ -1,162 +0,0 @@
1
- require 'parser/current'
2
-
3
- class Analyzer
4
-
5
- CONDITIONALS = [:if, :or_asgn, :and_asgn, :or, :and]
6
-
7
- attr_accessor :content, :class_name, :edges, :nodes, :exits
8
-
9
- DEFAULT_CLASS_NAME = "Unknown"
10
-
11
- def initialize(content)
12
- self.content = content
13
- self.edges = 0
14
- self.nodes = 1
15
- self.exits = 1
16
- end
17
-
18
- def complexity
19
- return unless traverse(parsed)
20
- self.edges - self.nodes + exits
21
- end
22
-
23
- def class_name
24
- find_class(parsed) || DEFAULT_CLASS_NAME
25
- end
26
-
27
- def methods
28
- @methods ||= methods_from(parsed)
29
- end
30
-
31
- def constants
32
- @constants ||= constants_from(parsed)
33
- end
34
-
35
- def method_names
36
- @method_names ||= method_names_from(parsed)
37
- end
38
-
39
- def extract_methods
40
- @methods ||= methods_from(parsed)
41
- end
42
-
43
- def extract_class_name
44
- return self.class_name if self.class_name && ! self.class_name.empty?
45
- found = find_class(parsed)
46
- self.class_name = ! found.empty? && found || DEFAULT_CLASS_NAME
47
- end
48
-
49
- private
50
-
51
- def method_list
52
- @method_list ||= method_names
53
- end
54
-
55
- def method_names_from(node, found=[])
56
- return found unless node.respond_to?(:type)
57
- if node.type == :def || node.type == :defs
58
- name = node.loc.name
59
- found << content[name.begin_pos..name.end_pos - 1].to_sym
60
- end
61
- node.children.each do |child|
62
- method_names_from(child, found) if parent_node?(child)
63
- end
64
- found
65
- end
66
-
67
- def constants_from(node, found=[])
68
- if node.type == :const
69
- expression = node.loc.expression
70
- found << content[expression.begin_pos..expression.end_pos - 1]
71
- end
72
- node.children.each do |child|
73
- constants_from(child, found) if parent_node?(child)
74
- end
75
- found.reject{ |constant| constant == class_name }
76
- end
77
-
78
- def extract_references_from(node, found=[])
79
- return found unless node && node.respond_to?(:type)
80
- if node.type == :send
81
- reference = node.loc.expression
82
- found << node.children.last
83
- end
84
- node.children.each do |child|
85
- extract_references_from(child, found)
86
- end
87
- found.select{|name| method_list.include?(name)}
88
- end
89
-
90
- def text_at(start_pos, end_pos)
91
- content[start_pos..end_pos - 1]
92
- end
93
-
94
- def find_class(node)
95
- return unless node && node.respond_to?(:type)
96
- concat = []
97
- if node.type == :module || node.type == :class
98
- concat << text_at(node.loc.name.begin_pos, node.loc.name.end_pos)
99
- end
100
- concat << node.children.map{|child| find_class(child)}.compact
101
- concat.flatten.select(&:present?).join('::')
102
- end
103
-
104
- def extend_graph
105
- self.edges += 2
106
- self.nodes += 2
107
- self.exits += 1
108
- end
109
-
110
- def methods_from(node, methods=[])
111
- if node.type == :def || node.type == :defs
112
- name = node.loc.name
113
- expression = node.loc.expression
114
- type = case(node.type)
115
- when :defs
116
- :class
117
- when :def
118
- :instance
119
- when :class
120
- :none
121
- end
122
- methods << ParsedMethod.new(
123
- name: content[name.begin_pos..name.end_pos - 1],
124
- content: content[expression.begin_pos..expression.end_pos - 1],
125
- type: type,
126
- refs: extract_references_from(node)
127
- )
128
- end
129
- node.children.each do |child|
130
- if parent_node?(child)
131
- methods_from(child, methods)
132
- end
133
- end
134
- methods.reject{ |m| m.name.empty? }
135
- end
136
-
137
- def parent_node?(node)
138
- node.respond_to?(:type) || node.respond_to?(:children)
139
- end
140
-
141
- def parse!
142
- traverse(parsed) && complexity
143
- end
144
-
145
- def parsed
146
- @parsed ||= Parser::CurrentRuby.parse(content)
147
- end
148
-
149
- def traverse(node, accumulator=[], extract_methods=false)
150
- accumulator << node.type
151
- extend_graph if CONDITIONALS.include?(node.type)
152
- node.children.each do |child|
153
- if parent_node?(child)
154
- accumulator << child.type
155
- traverse(child, accumulator)
156
- end
157
- end
158
- accumulator
159
- end
160
-
161
- end
162
-
@@ -1,19 +0,0 @@
1
- class LineOfCode
2
-
3
- include PoroPlus
4
- include Ephemeral::Base
5
-
6
- attr_accessor :line_number, :range, :content
7
-
8
- def self.containing(locs, start_index, end_index)
9
- locs.inject([]) do |a, loc|
10
- a << loc if loc.in_range?(start_index) || loc.in_range?(end_index)
11
- a
12
- end.compact
13
- end
14
-
15
- def in_range?(index)
16
- self.range.include?(index)
17
- end
18
-
19
- end