guideline 0.0.7 → 0.0.8

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.
data/bin/guideline CHANGED
@@ -8,6 +8,7 @@ options = Runner.parse(ARGV)
8
8
 
9
9
  checkers = CheckerFactory.new(
10
10
  options[:config],
11
+ AbcComplexityChecker,
11
12
  UnusedMethodChecker,
12
13
  HashCommaChecker,
13
14
  LongLineChecker,
data/guideline.yml CHANGED
@@ -2,3 +2,5 @@
2
2
  max: 80
3
3
  "Guideline::LongMethodChecker":
4
4
  max: 10
5
+ "Guideline::AbcComplexityChecker":
6
+ max: 10
@@ -0,0 +1,151 @@
1
+ require "ripper"
2
+
3
+ module Guideline
4
+ class AbcComplexityChecker < Checker
5
+ def check(path)
6
+ @current_path = path
7
+ visitor.check(path.to_s, path.read)
8
+ @current_path = nil
9
+ end
10
+
11
+ private
12
+
13
+ def checker
14
+ AbcParser.new do |complexity, method, module_name, class_method_flag|
15
+ if complexity > max
16
+ report(
17
+ :path => @current_path,
18
+ :line => method.line,
19
+ :message => "ABC Complexity of method<%s%s%s>%3d should be less than %d" % [
20
+ module_name,
21
+ class_method_flag ? "." : "#",
22
+ method.method_name,
23
+ complexity,
24
+ max,
25
+ ]
26
+ )
27
+ end
28
+ end
29
+ end
30
+
31
+ def visitor
32
+ CodeAnalyzer::CheckingVisitor::Default.new(checkers: [checker])
33
+ end
34
+
35
+ def max
36
+ @options[:max]
37
+ end
38
+
39
+ module Moduleable
40
+ def self.included(base)
41
+ base.class_eval do
42
+ interesting_nodes :class, :module
43
+
44
+ add_callback :start_class do |node|
45
+ modules << node.class_name.to_s
46
+ end
47
+
48
+ add_callback :start_module do |node|
49
+ modules << node.module_name.to_s
50
+ end
51
+
52
+ add_callback :end_class do |node|
53
+ modules.pop
54
+ end
55
+
56
+ add_callback :end_module do |node|
57
+ modules.pop
58
+ end
59
+ end
60
+ end
61
+
62
+ def current_module_name
63
+ modules.join("::")
64
+ end
65
+
66
+ def modules
67
+ @moduels ||= []
68
+ end
69
+ end
70
+
71
+ class AbcParser < CodeAnalyzer::Checker
72
+ ASSIGNMENT_NODES = [:assign, :opassign]
73
+ BRANCH_NODES = [:call, :fcall, :vcall, :zsuper, :yield0, :brace_block, :do_block]
74
+ CONDITION_NODES = [:else]
75
+ CONDITION_TOKENS = [:==, :===, :"<>", :<=, :>=, :=~, :>, :<, :<=>]
76
+ ALL_NODES = ASSIGNMENT_NODES + BRANCH_NODES + CONDITION_NODES
77
+
78
+ include Moduleable
79
+
80
+ attr_reader :assignment, :branch, :condition
81
+
82
+ interesting_files /.*\.rb/
83
+ interesting_nodes :def, :defs, :binary, :zsuper, *ALL_NODES
84
+
85
+ ASSIGNMENT_NODES.each do |name|
86
+ add_callback :"start_#{name}" do |node|
87
+ @assignment += 1
88
+ end
89
+ end
90
+
91
+ BRANCH_NODES.each do |name|
92
+ add_callback :"start_#{name}" do |node|
93
+ @branch += 1
94
+ end
95
+ end
96
+
97
+ CONDITION_NODES.each do |name|
98
+ add_callback :"start_#{name}" do |node|
99
+ @condition += 1
100
+ end
101
+ end
102
+
103
+ add_callback :start_def do |node|
104
+ @current_method = node
105
+ clear
106
+ end
107
+
108
+ add_callback :start_defs do |node|
109
+ @current_method = node
110
+ clear
111
+ end
112
+
113
+ add_callback :end_def do |node|
114
+ @callback.call(complexity, @current_method, current_module_name, false)
115
+ @current_method = nil
116
+ end
117
+
118
+ add_callback :end_defs do |node|
119
+ @callback.call(complexity, @current_method, current_module_name, true)
120
+ @current_method = nil
121
+ end
122
+
123
+ add_callback :start_binary do |node|
124
+ @condition += 1 if condition_table[node[2]]
125
+ end
126
+
127
+ def initialize(*, &callback)
128
+ clear
129
+ @callback = callback
130
+ super
131
+ end
132
+
133
+ def clear
134
+ @assignment = 0
135
+ @branch = 0
136
+ @condition = 0
137
+ end
138
+
139
+ def complexity
140
+ Math.sqrt(@assignment ** 2 + @branch ** 2 + @condition ** 2)
141
+ end
142
+
143
+ def condition_table
144
+ @condition_table ||= CONDITION_TOKENS.inject({}) do |hash, token|
145
+ hash[token] = true
146
+ hash
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -1,3 +1,3 @@
1
1
  module Guideline
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
data/lib/guideline.rb CHANGED
@@ -9,3 +9,4 @@ require "guideline/checkers/long_method_checker"
9
9
  require "guideline/checkers/hard_tab_indent_checker"
10
10
  require "guideline/checkers/hash_comma_checker"
11
11
  require "guideline/checkers/unused_method_checker"
12
+ require "guideline/checkers/abc_complexity_checker"
@@ -0,0 +1,171 @@
1
+ require "spec_helper"
2
+
3
+ module Guideline
4
+ describe AbcComplexityChecker do
5
+ describe "#check" do
6
+ subject do
7
+ checker.check(path)
8
+ checker
9
+ end
10
+
11
+ let(:checker) do
12
+ described_class.new(:max => 1.4)
13
+ end
14
+
15
+ let(:path) do
16
+ mock(:read => script, :to_s => "mock.rb")
17
+ end
18
+
19
+ context "when there is a few assignment" do
20
+ let(:script) do
21
+ <<-EOF
22
+ def a
23
+ b = 1
24
+ end
25
+ EOF
26
+ end
27
+ it { should_not have_error }
28
+ end
29
+
30
+ context "when there is too much assign" do
31
+ let(:script) do
32
+ <<-EOF
33
+ def a
34
+ b = 1
35
+ c = 2
36
+ end
37
+ EOF
38
+ end
39
+ it { should have_error }
40
+ end
41
+
42
+ context "when there is too much opassign" do
43
+ let(:script) do
44
+ <<-EOF
45
+ def a
46
+ b += 1
47
+ c += 1
48
+ end
49
+ EOF
50
+ end
51
+ it { should have_error }
52
+ end
53
+
54
+ context "when there is too much else statement" do
55
+ let(:script) do
56
+ <<-EOF
57
+ def a
58
+ if b
59
+ 1
60
+ else
61
+ 2
62
+ end
63
+
64
+ if c
65
+ 3
66
+ else
67
+ 4
68
+ end
69
+ end
70
+ EOF
71
+ end
72
+ it { should have_error }
73
+ end
74
+
75
+ context "when there is too much comparison operator" do
76
+ let(:script) do
77
+ <<-EOF
78
+ def a
79
+ b == 1
80
+ c == 2
81
+ end
82
+ EOF
83
+ end
84
+ it { should have_error }
85
+ end
86
+
87
+ context "when there is too much fcall" do
88
+ let(:script) do
89
+ <<-EOF
90
+ def a
91
+ b()
92
+ c()
93
+ end
94
+ EOF
95
+ end
96
+ it { should have_error }
97
+ end
98
+
99
+ context "when there is too much vcall" do
100
+ let(:script) do
101
+ <<-EOF
102
+ def a
103
+ b
104
+ c
105
+ end
106
+ EOF
107
+ end
108
+ it { should have_error }
109
+ end
110
+
111
+ context "when there is too much call and vcall" do
112
+ let(:script) do
113
+ <<-EOF
114
+ def a
115
+ b.c
116
+ end
117
+ EOF
118
+ end
119
+ it { should have_error }
120
+ end
121
+
122
+ context "when there is too much vcall and do_block" do
123
+ let(:script) do
124
+ <<-EOF
125
+ def a
126
+ a do
127
+ 1
128
+ end
129
+ end
130
+ EOF
131
+ end
132
+ it { should have_error }
133
+ end
134
+
135
+ context "when there is too much vcall and brace_block" do
136
+ let(:script) do
137
+ <<-EOF
138
+ def a
139
+ a { 1 }
140
+ end
141
+ EOF
142
+ end
143
+ it { should have_error }
144
+ end
145
+
146
+ context "when there is too much yield" do
147
+ let(:script) do
148
+ <<-EOF
149
+ def a
150
+ yield
151
+ yield
152
+ end
153
+ EOF
154
+ end
155
+ it { should have_error }
156
+ end
157
+
158
+ context "when there is too much super" do
159
+ let(:script) do
160
+ <<-EOF
161
+ def a
162
+ super
163
+ super
164
+ end
165
+ EOF
166
+ end
167
+ it { should have_error }
168
+ end
169
+ end
170
+ end
171
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guideline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-29 00:00:00.000000000 Z
12
+ date: 2012-11-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: slop
@@ -125,6 +125,7 @@ files:
125
125
  - guideline.yml
126
126
  - lib/guideline.rb
127
127
  - lib/guideline/checker_factory.rb
128
+ - lib/guideline/checkers/abc_complexity_checker.rb
128
129
  - lib/guideline/checkers/checker.rb
129
130
  - lib/guideline/checkers/hard_tab_indent_checker.rb
130
131
  - lib/guideline/checkers/hash_comma_checker.rb
@@ -136,6 +137,7 @@ files:
136
137
  - lib/guideline/version.rb
137
138
  - lib/guideline/visitor.rb
138
139
  - spec/guideline/checker_factory_spec.rb
140
+ - spec/guideline/checkers/abc_complexity_checker_spec.rb
139
141
  - spec/guideline/checkers/checker_spec.rb
140
142
  - spec/guideline/checkers/hard_tab_indent_checker_spec.rb
141
143
  - spec/guideline/checkers/hash_comma_checker_spec.rb
@@ -172,6 +174,7 @@ specification_version: 3
172
174
  summary: The guideline of your code
173
175
  test_files:
174
176
  - spec/guideline/checker_factory_spec.rb
177
+ - spec/guideline/checkers/abc_complexity_checker_spec.rb
175
178
  - spec/guideline/checkers/checker_spec.rb
176
179
  - spec/guideline/checkers/hard_tab_indent_checker_spec.rb
177
180
  - spec/guideline/checkers/hash_comma_checker_spec.rb