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 +1 -0
- data/guideline.yml +2 -0
- data/lib/guideline/checkers/abc_complexity_checker.rb +151 -0
- data/lib/guideline/version.rb +1 -1
- data/lib/guideline.rb +1 -0
- data/spec/guideline/checkers/abc_complexity_checker_spec.rb +171 -0
- metadata +5 -2
data/bin/guideline
CHANGED
data/guideline.yml
CHANGED
@@ -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
|
data/lib/guideline/version.rb
CHANGED
data/lib/guideline.rb
CHANGED
@@ -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.
|
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-
|
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
|