excellent 1.5.4 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/README.rdoc +2 -2
- data/bin/excellent +32 -14
- data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +2 -2
- data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +2 -2
- data/lib/simplabs/excellent/checks/base.rb +9 -7
- data/lib/simplabs/excellent/checks/case_missing_else_check.rb +2 -2
- data/lib/simplabs/excellent/checks/class_line_count_check.rb +1 -1
- data/lib/simplabs/excellent/checks/class_name_check.rb +1 -1
- data/lib/simplabs/excellent/checks/control_coupling_check.rb +1 -1
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +1 -1
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +3 -3
- data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +1 -1
- data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +1 -1
- data/lib/simplabs/excellent/checks/flog_block_check.rb +1 -1
- data/lib/simplabs/excellent/checks/flog_check.rb +3 -3
- data/lib/simplabs/excellent/checks/flog_class_check.rb +1 -1
- data/lib/simplabs/excellent/checks/flog_method_check.rb +1 -1
- data/lib/simplabs/excellent/checks/for_loop_check.rb +2 -2
- data/lib/simplabs/excellent/checks/global_variable_check.rb +2 -2
- data/lib/simplabs/excellent/checks/line_count_check.rb +3 -3
- data/lib/simplabs/excellent/checks/method_line_count_check.rb +1 -1
- data/lib/simplabs/excellent/checks/method_name_check.rb +1 -1
- data/lib/simplabs/excellent/checks/module_line_count_check.rb +1 -1
- data/lib/simplabs/excellent/checks/module_name_check.rb +1 -1
- data/lib/simplabs/excellent/checks/name_check.rb +3 -3
- data/lib/simplabs/excellent/checks/nested_iterators_check.rb +2 -2
- data/lib/simplabs/excellent/checks/parameter_number_check.rb +2 -2
- data/lib/simplabs/excellent/checks/rails/attr_accessible_check.rb +1 -1
- data/lib/simplabs/excellent/checks/rails/attr_protected_check.rb +1 -1
- data/lib/simplabs/excellent/checks/rails/custom_initialize_method_check.rb +1 -1
- data/lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb +2 -2
- data/lib/simplabs/excellent/checks/rails/params_hash_in_view_check.rb +3 -3
- data/lib/simplabs/excellent/checks/rails/session_hash_in_view_check.rb +3 -3
- data/lib/simplabs/excellent/checks/rails/validations_check.rb +1 -1
- data/lib/simplabs/excellent/checks/singleton_variable_check.rb +1 -1
- data/lib/simplabs/excellent/formatters/html.rb +103 -7
- data/lib/simplabs/excellent/parsing/call_context.rb +11 -1
- data/lib/simplabs/excellent/parsing/code_processor.rb +15 -13
- data/lib/simplabs/excellent/parsing/constant_context.rb +20 -0
- data/lib/simplabs/excellent/parsing/cvar_context.rb +1 -1
- data/lib/simplabs/excellent/parsing/gasgn_context.rb +21 -0
- data/lib/simplabs/excellent/parsing/ivar_context.rb +1 -1
- data/lib/simplabs/excellent/parsing/method_context.rb +1 -1
- data/lib/simplabs/excellent/parsing/parser.rb +0 -1
- data/lib/simplabs/excellent/parsing/sexp_context.rb +10 -1
- data/lib/simplabs/excellent/parsing/singleton_method_context.rb +1 -1
- data/lib/simplabs/excellent/rake/excellent_task.rb +1 -1
- data/spec/checks/rails/validations_check_spec.rb +1 -1
- metadata +44 -57
data/History.txt
CHANGED
data/README.rdoc
CHANGED
@@ -46,7 +46,7 @@ To analyse all the models in your Rails application, just do
|
|
46
46
|
in your <tt>RAILS_ROOT</tt>. You can also invoke analysation through the Simplabs::Excellent::Runner class. Excellent can also produce HTML output. To
|
47
47
|
get a formatted HTML report, just specify <tt>html:<filename></tt>:
|
48
48
|
|
49
|
-
excellent
|
49
|
+
excellent -o out.html app/models
|
50
50
|
|
51
51
|
You can also use Excellent in a Rake task:
|
52
52
|
|
@@ -67,6 +67,6 @@ If you want to contribute, just fork the repo. Also I would appretiate suggestio
|
|
67
67
|
|
68
68
|
== Author
|
69
69
|
|
70
|
-
Copyright (c) 2008-
|
70
|
+
Copyright (c) 2008-2010 Marco Otte-Witte (http://simplabs.com), released under the MIT license.
|
71
71
|
|
72
72
|
Excellent was inspired by roodi (http://github.com/martinjandrews/roodi), reek (http://github.com/kevinrutherford/reek) and flog (http://github.com/seattlerb/flog).
|
data/bin/excellent
CHANGED
@@ -1,31 +1,49 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
4
|
-
|
5
3
|
require 'simplabs/excellent'
|
6
4
|
require 'pathname'
|
5
|
+
require 'optparse'
|
7
6
|
|
8
|
-
|
7
|
+
options = {}
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
optparse = OptionParser.new do |opt|
|
10
|
+
opt.banner = 'Usage: excellent [OPTIONS] <PATH1> [<PATH2> ...]'
|
11
|
+
opt.on('--output', '-o [FILE]', 'Write HTML output to [FILE].') do |target|
|
12
|
+
options[:output] = target
|
13
|
+
end
|
14
|
+
opt.on_tail('--help', '-h', 'Help') do
|
15
|
+
puts optparse
|
16
|
+
exit
|
16
17
|
end
|
17
|
-
else
|
18
|
-
formatter = Simplabs::Excellent::Formatters::Text.new
|
19
18
|
end
|
20
19
|
|
21
|
-
|
20
|
+
optparse.parse!
|
21
|
+
|
22
|
+
target = options[:output]
|
23
|
+
paths = ARGV.dup
|
24
|
+
|
25
|
+
if paths.empty?
|
22
26
|
puts "\n You must specify one or more directories to analyse, e.g.:\n"
|
23
|
-
puts "\n excellent
|
27
|
+
puts "\n excellent lib/\n\n"
|
24
28
|
exit 1
|
25
29
|
end
|
26
30
|
|
31
|
+
if target
|
32
|
+
begin
|
33
|
+
fileio = File.open(target, 'w+')
|
34
|
+
formatter = Simplabs::Excellent::Formatters::Html.new(fileio)
|
35
|
+
rescue Errno::ENOENT
|
36
|
+
puts "\n #{target} cannot be opened for writing. Specify a file name like so:\n"
|
37
|
+
puts "\n excellent -o excellent.html lib/\n\n"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
formatter = Simplabs::Excellent::Formatters::Text.new
|
41
|
+
end
|
42
|
+
|
43
|
+
excellent = Simplabs::Excellent::Runner.new
|
44
|
+
|
27
45
|
begin
|
28
|
-
excellent.check_paths(
|
46
|
+
excellent.check_paths(paths, formatter)
|
29
47
|
rescue ArgumentError
|
30
48
|
puts "\n** Excellent cannot find the paths specified!\n\n"
|
31
49
|
exit 1
|
@@ -24,8 +24,8 @@ module Simplabs
|
|
24
24
|
|
25
25
|
def initialize(options = {}) #:nodoc:
|
26
26
|
super()
|
27
|
-
@threshold
|
28
|
-
@
|
27
|
+
@threshold = options[:threshold] || DEFAULT_THRESHOLD
|
28
|
+
@interesting_contexts = [Parsing::MethodContext, Parsing::SingletonMethodContext]
|
29
29
|
end
|
30
30
|
|
31
31
|
def evaluate(context) #:nodoc:
|
@@ -22,8 +22,8 @@ module Simplabs
|
|
22
22
|
|
23
23
|
def initialize(options = {}) #:nodoc:
|
24
24
|
super()
|
25
|
-
@
|
26
|
-
@interesting_files
|
25
|
+
@interesting_contexts = [Parsing::IfContext, Parsing::WhileContext, Parsing::UntilContext]
|
26
|
+
@interesting_files = [/\.rb$/, /\.erb$/]
|
27
27
|
end
|
28
28
|
|
29
29
|
def evaluate(context) #:nodoc:
|
@@ -6,15 +6,16 @@ module Simplabs
|
|
6
6
|
|
7
7
|
module Checks
|
8
8
|
|
9
|
-
# This is the base class for all code checks. All checks must specify +
|
10
|
-
# will invoke the +
|
9
|
+
# This is the base class for all code checks. All checks must specify +interesting_contexts+. When one of these contexts is processed by Excellent, it
|
10
|
+
# will invoke the +evaluate_context+ method of all checks that specify the context as one if their +interesting_contexts+.
|
11
11
|
class Base
|
12
12
|
|
13
13
|
attr_reader :warnings
|
14
14
|
|
15
|
-
# An array of
|
16
|
-
#
|
17
|
-
|
15
|
+
# An array of contexts that are interesting for the check. These contexts are based on symbols as returned by RubyParser (see
|
16
|
+
# http://parsetree.rubyforge.org/ruby_parser/) and add some additional data,
|
17
|
+
# e.g. <tt>Ifcontext</tt> or <tt>MethodContext</tt>
|
18
|
+
attr_reader :interesting_contexts
|
18
19
|
|
19
20
|
# An array of regular expressions for file names that are interesting for the check. These will usually be path extensions rather than longer
|
20
21
|
# patterns (e.g. *.rb as well as *.erb files or *.rb files only).
|
@@ -27,12 +28,13 @@ module Simplabs
|
|
27
28
|
@interesting_files = [/\.rb$/]
|
28
29
|
end
|
29
30
|
|
30
|
-
# This method is called whenever Excellent processes a
|
31
|
+
# This method is called whenever Excellent processes a context that the check specified as one of the contexts it is interested in (see
|
32
|
+
# interesting_contexts).
|
31
33
|
#
|
32
34
|
# ==== Parameters
|
33
35
|
#
|
34
36
|
# * <tt>context</tt> - This is the last context the code processor has constructed. It contains all information required to execute the check (see Simplabs::Excellent::Parsing::SexpContext).
|
35
|
-
def
|
37
|
+
def evaluate_context(context)
|
36
38
|
evaluate(context)
|
37
39
|
end
|
38
40
|
|
@@ -17,8 +17,8 @@ module Simplabs
|
|
17
17
|
|
18
18
|
def initialize #:nodoc:
|
19
19
|
super
|
20
|
-
@
|
21
|
-
@interesting_files
|
20
|
+
@interesting_contexts = [Parsing::CaseContext]
|
21
|
+
@interesting_files = [/\.rb$/, /\.erb$/]
|
22
22
|
end
|
23
23
|
|
24
24
|
def evaluate(context) #:nodoc:
|
@@ -8,10 +8,10 @@ module Simplabs
|
|
8
8
|
|
9
9
|
class CyclomaticComplexityCheck < Base #:nodoc:
|
10
10
|
|
11
|
-
def initialize(
|
11
|
+
def initialize(interesting_contexts, threshold)
|
12
12
|
super()
|
13
|
-
@
|
14
|
-
@threshold
|
13
|
+
@interesting_contexts = interesting_contexts
|
14
|
+
@threshold = threshold
|
15
15
|
end
|
16
16
|
|
17
17
|
end
|
@@ -30,7 +30,7 @@ module Simplabs
|
|
30
30
|
|
31
31
|
def initialize(options = {}) #:nodoc:
|
32
32
|
threshold = options[:threshold] || DEFAULT_THRESHOLD
|
33
|
-
super([
|
33
|
+
super([Parsing::MethodContext, Parsing::SingletonMethodContext], threshold)
|
34
34
|
end
|
35
35
|
|
36
36
|
def evaluate(context) #:nodoc:
|
@@ -8,10 +8,10 @@ module Simplabs
|
|
8
8
|
|
9
9
|
class FlogCheck < Base #:nodoc:
|
10
10
|
|
11
|
-
def initialize(
|
11
|
+
def initialize(interesting_contexts, threshold)
|
12
12
|
super()
|
13
|
-
@
|
14
|
-
@threshold
|
13
|
+
@interesting_contexts = interesting_contexts
|
14
|
+
@threshold = threshold
|
15
15
|
end
|
16
16
|
|
17
17
|
def evaluate(context)
|
@@ -25,8 +25,8 @@ module Simplabs
|
|
25
25
|
|
26
26
|
def initialize #:nodoc:
|
27
27
|
super
|
28
|
-
@
|
29
|
-
@interesting_files
|
28
|
+
@interesting_contexts = [Parsing::ForLoopContext]
|
29
|
+
@interesting_files = [/\.rb$/, /\.erb$/]
|
30
30
|
end
|
31
31
|
|
32
32
|
def evaluate(context) #:nodoc:
|
@@ -16,8 +16,8 @@ module Simplabs
|
|
16
16
|
|
17
17
|
def initialize #:nodoc:
|
18
18
|
super
|
19
|
-
@
|
20
|
-
@interesting_files
|
19
|
+
@interesting_contexts = [Parsing::GvarContext, Parsing::GasgnContext]
|
20
|
+
@interesting_files = [/\.rb$/, /\.erb$/]
|
21
21
|
end
|
22
22
|
|
23
23
|
def evaluate(context) #:nodoc:
|
@@ -8,10 +8,10 @@ module Simplabs
|
|
8
8
|
|
9
9
|
class LineCountCheck < Base #:nodoc:
|
10
10
|
|
11
|
-
def initialize(
|
11
|
+
def initialize(interesting_contexts, threshold)
|
12
12
|
super()
|
13
|
-
@
|
14
|
-
@threshold
|
13
|
+
@interesting_contexts = interesting_contexts
|
14
|
+
@threshold = threshold
|
15
15
|
end
|
16
16
|
|
17
17
|
def evaluate(context)
|
@@ -8,10 +8,10 @@ module Simplabs
|
|
8
8
|
|
9
9
|
class NameCheck < Base #:nodoc:
|
10
10
|
|
11
|
-
def initialize(
|
11
|
+
def initialize(interesting_contexts, pattern)
|
12
12
|
super()
|
13
|
-
@
|
14
|
-
@pattern
|
13
|
+
@interesting_contexts = interesting_contexts
|
14
|
+
@pattern = pattern
|
15
15
|
end
|
16
16
|
|
17
17
|
def evaluate(context)
|
@@ -15,8 +15,8 @@ module Simplabs
|
|
15
15
|
|
16
16
|
def initialize #:nodoc:
|
17
17
|
super
|
18
|
-
@
|
19
|
-
@interesting_files
|
18
|
+
@interesting_contexts = [Parsing::BlockContext]
|
19
|
+
@interesting_files = [/\.rb$/, /\.erb$/]
|
20
20
|
end
|
21
21
|
|
22
22
|
def evaluate(context) #:nodoc:
|
@@ -19,8 +19,8 @@ module Simplabs
|
|
19
19
|
|
20
20
|
def initialize(options = {}) #:nodoc:
|
21
21
|
super()
|
22
|
-
@threshold
|
23
|
-
@
|
22
|
+
@threshold = options[:threshold] || DEFAULT_THRESHOLD
|
23
|
+
@interesting_contexts = [Parsing::MethodContext, Parsing::SingletonMethodContext, Parsing::BlockContext]
|
24
24
|
end
|
25
25
|
|
26
26
|
def evaluate(context) #:nodoc:
|
@@ -18,12 +18,12 @@ module Simplabs
|
|
18
18
|
|
19
19
|
def initialize #:nodoc:
|
20
20
|
super
|
21
|
-
@
|
21
|
+
@interesting_contexts = [Parsing::IvarContext]
|
22
22
|
@interesting_files = [/^_.*\.erb$/]
|
23
23
|
end
|
24
24
|
|
25
25
|
def evaluate(context) #:nodoc:
|
26
|
-
add_warning(context, 'Instance variable {{variable}} used in partial.', { :variable => context.full_name })
|
26
|
+
add_warning(context, 'Instance variable {{variable}} used in partial.', { :variable => context.full_name }, -1)
|
27
27
|
end
|
28
28
|
|
29
29
|
end
|
@@ -19,12 +19,12 @@ module Simplabs
|
|
19
19
|
|
20
20
|
def initialize #:nodoc:
|
21
21
|
super
|
22
|
-
@
|
23
|
-
@interesting_files
|
22
|
+
@interesting_contexts = [Parsing::CallContext]
|
23
|
+
@interesting_files = [/^.*\.(erb|rhtml)$/]
|
24
24
|
end
|
25
25
|
|
26
26
|
def evaluate(context) #:nodoc:
|
27
|
-
add_warning(context, 'Params hash used in view.') if (context.full_name == 'params')
|
27
|
+
add_warning(context, 'Params hash used in view.', {}, -1) if (context.full_name == 'params')
|
28
28
|
end
|
29
29
|
|
30
30
|
end
|
@@ -19,12 +19,12 @@ module Simplabs
|
|
19
19
|
|
20
20
|
def initialize #:nodoc:
|
21
21
|
super
|
22
|
-
@
|
23
|
-
@interesting_files = [/^.*\.(erb|rhtml)$/]
|
22
|
+
@interesting_contexts = [Parsing::CallContext]
|
23
|
+
@interesting_files = [/^.*\.(erb|rhtml|haml)$/]
|
24
24
|
end
|
25
25
|
|
26
26
|
def evaluate(context) #:nodoc:
|
27
|
-
add_warning(context, 'Session hash used in view.') if (context.full_name == 'session')
|
27
|
+
add_warning(context, 'Session hash used in view.', {}, -1) if (context.full_name == 'session')
|
28
28
|
end
|
29
29
|
|
30
30
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'simplabs/excellent/formatters/base'
|
2
|
+
require 'rubygems'
|
2
3
|
|
3
4
|
module Simplabs
|
4
5
|
|
@@ -71,14 +72,11 @@ module Simplabs
|
|
71
72
|
}
|
72
73
|
|
73
74
|
dd {
|
74
|
-
|
75
|
-
}
|
76
|
-
|
77
|
-
dd.warning {
|
75
|
+
margin: 5px 0px 5px 20px;
|
78
76
|
background: #faf834;
|
79
77
|
}
|
80
78
|
|
81
|
-
dd
|
79
|
+
dd span.lineNumber {
|
82
80
|
background: #ccc;
|
83
81
|
font-weight: bold;
|
84
82
|
padding: 3px;
|
@@ -86,7 +84,7 @@ module Simplabs
|
|
86
84
|
margin: 0 10px 0 0;
|
87
85
|
}
|
88
86
|
|
89
|
-
dd
|
87
|
+
dd span.number {
|
90
88
|
width: 30px;
|
91
89
|
text-align: right;
|
92
90
|
display: inline-block;
|
@@ -109,6 +107,102 @@ module Simplabs
|
|
109
107
|
color: #fff;
|
110
108
|
background-color: #222;
|
111
109
|
}
|
110
|
+
|
111
|
+
.af { color:#00C }
|
112
|
+
.an { color:#007 }
|
113
|
+
.at { color:#f08 }
|
114
|
+
.av { color:#700 }
|
115
|
+
.aw { color:#C00 }
|
116
|
+
.bi { color:#509; font-weight:bold }
|
117
|
+
.c { color:#888; }
|
118
|
+
|
119
|
+
.ch { color:#04D }
|
120
|
+
.ch .k { color:#04D }
|
121
|
+
.ch .dl { color:#039 }
|
122
|
+
|
123
|
+
.cl { color:#B06; font-weight:bold }
|
124
|
+
.co { color:#036; font-weight:bold }
|
125
|
+
.cr { color:#0A0 }
|
126
|
+
.cv { color:#369 }
|
127
|
+
.df { color:#099; font-weight:bold }
|
128
|
+
.di { color:#088; font-weight:bold }
|
129
|
+
.dl { color:black }
|
130
|
+
.do { color:#970 }
|
131
|
+
.dt { color:#34b }
|
132
|
+
.ds { color:#D42; font-weight:bold }
|
133
|
+
.e { color:#666; font-weight:bold }
|
134
|
+
.en { color:#800; font-weight:bold }
|
135
|
+
.er { color:#F00; background-color:#FAA }
|
136
|
+
.ex { color:#F00; font-weight:bold }
|
137
|
+
.fl { color:#60E; font-weight:bold }
|
138
|
+
.fu { color:#06B; font-weight:bold }
|
139
|
+
.gv { color:#d70; font-weight:bold }
|
140
|
+
.hx { color:#058; font-weight:bold }
|
141
|
+
.i { color:#00D; font-weight:bold }
|
142
|
+
.ic { color:#B44; font-weight:bold }
|
143
|
+
|
144
|
+
.il { background: #eee; color: black }
|
145
|
+
.il .il { background: #ddd }
|
146
|
+
.il .il .il { background: #ccc }
|
147
|
+
.il .idl { font-weight: bold; color: #777 }
|
148
|
+
|
149
|
+
.im { color:#f00; }
|
150
|
+
.in { color:#B2B; font-weight:bold }
|
151
|
+
.iv { color:#33B }
|
152
|
+
.la { color:#970; font-weight:bold }
|
153
|
+
.lv { color:#963 }
|
154
|
+
.oc { color:#40E; font-weight:bold }
|
155
|
+
.of { color:#000; font-weight:bold }
|
156
|
+
.op { }
|
157
|
+
.pc { color:#038; font-weight:bold }
|
158
|
+
.pd { color:#369; font-weight:bold }
|
159
|
+
.pp { color:#579; }
|
160
|
+
.ps { color:#00C; font-weight: bold; }
|
161
|
+
.pt { color:#349; font-weight:bold }
|
162
|
+
.r, .kw { color:#080; font-weight:bold }
|
163
|
+
|
164
|
+
.ke { color: #808; }
|
165
|
+
.ke .dl { color: #606; }
|
166
|
+
.ke .ch { color: #80f; }
|
167
|
+
.vl { color: #088; }
|
168
|
+
|
169
|
+
.rx { background-color:#fff0ff }
|
170
|
+
.rx .k { color:#808 }
|
171
|
+
.rx .dl { color:#404 }
|
172
|
+
.rx .mod { color:#C2C }
|
173
|
+
.rx .fu { color:#404; font-weight: bold }
|
174
|
+
|
175
|
+
.s { background-color:#fff0f0; color: #D20; }
|
176
|
+
.s .s { background-color:#ffe0e0 }
|
177
|
+
.s .s .s { background-color:#ffd0d0 }
|
178
|
+
.s .k { }
|
179
|
+
.s .ch { color: #b0b; }
|
180
|
+
.s .dl { color: #710; }
|
181
|
+
|
182
|
+
.sh { background-color:#f0fff0; color:#2B2 }
|
183
|
+
.sh .k { }
|
184
|
+
.sh .dl { color:#161 }
|
185
|
+
|
186
|
+
.sy { color:#A60 }
|
187
|
+
.sy .k { color:#A60 }
|
188
|
+
.sy .dl { color:#630 }
|
189
|
+
|
190
|
+
.ta { color:#070 }
|
191
|
+
.tf { color:#070; font-weight:bold }
|
192
|
+
.ts { color:#D70; font-weight:bold }
|
193
|
+
.ty { color:#339; font-weight:bold }
|
194
|
+
.v { color:#036 }
|
195
|
+
.xt { color:#444 }
|
196
|
+
|
197
|
+
.ins { background: #afa; }
|
198
|
+
.del { background: #faa; }
|
199
|
+
.chg { color: #aaf; background: #007; }
|
200
|
+
.head { color: #f8f; background: #505 }
|
201
|
+
|
202
|
+
.ins .ins { color: #080; font-weight:bold }
|
203
|
+
.del .del { color: #800; font-weight:bold }
|
204
|
+
.chg .chg { color: #66f; }
|
205
|
+
.head .head { color: #f4f; }
|
112
206
|
</style>
|
113
207
|
</head>
|
114
208
|
<body>
|
@@ -132,7 +226,9 @@ module Simplabs
|
|
132
226
|
END
|
133
227
|
|
134
228
|
WARNING_TEMPLATE = <<-END
|
135
|
-
<dd
|
229
|
+
<dd>
|
230
|
+
<span class="lineNumber">Line <span class="number">{{line_number}}</span></span>{{message}}
|
231
|
+
</dd>
|
136
232
|
END
|
137
233
|
|
138
234
|
FOOTER_TEMPLATE = <<-END
|
@@ -13,7 +13,17 @@ module Simplabs
|
|
13
13
|
|
14
14
|
def initialize(exp, parent)
|
15
15
|
super
|
16
|
-
@receiver = exp[1].is_a?(Sexp)
|
16
|
+
@receiver = if exp[1].is_a?(Sexp) && exp[1].node_type == :colon2
|
17
|
+
resolve_colon(exp[1])
|
18
|
+
elsif exp[1].is_a?(Sexp)
|
19
|
+
if exp[1].node_type != :call
|
20
|
+
exp[1][1].nil? ? exp[1][2].to_s : exp[1][1].to_s
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
17
27
|
@method = exp[2].to_s
|
18
28
|
@full_name = [@receiver, @method].compact.join('.')
|
19
29
|
record_validation
|
@@ -12,9 +12,11 @@ require 'simplabs/excellent/parsing/while_context'
|
|
12
12
|
require 'simplabs/excellent/parsing/until_context'
|
13
13
|
require 'simplabs/excellent/parsing/cvar_context'
|
14
14
|
require 'simplabs/excellent/parsing/gvar_context'
|
15
|
+
require 'simplabs/excellent/parsing/gasgn_context'
|
15
16
|
require 'simplabs/excellent/parsing/ivar_context'
|
16
17
|
require 'simplabs/excellent/parsing/resbody_context'
|
17
18
|
require 'simplabs/excellent/parsing/call_context'
|
19
|
+
require 'simplabs/excellent/parsing/constant_context'
|
18
20
|
|
19
21
|
module Simplabs
|
20
22
|
|
@@ -35,8 +37,6 @@ module Simplabs
|
|
35
37
|
|
36
38
|
def process(exp)
|
37
39
|
super
|
38
|
-
rescue
|
39
|
-
#continue on errors
|
40
40
|
end
|
41
41
|
|
42
42
|
def process_class(exp)
|
@@ -68,7 +68,7 @@ module Simplabs
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def process_gasgn(exp)
|
71
|
-
process_default(exp,
|
71
|
+
process_default(exp, GasgnContext.new(exp, @contexts.last))
|
72
72
|
end
|
73
73
|
|
74
74
|
def process_if(exp)
|
@@ -113,6 +113,10 @@ module Simplabs
|
|
113
113
|
process_default(exp, ResbodyContext.new(exp, @contexts.last))
|
114
114
|
end
|
115
115
|
|
116
|
+
def process_cdecl(exp)
|
117
|
+
process_default(exp, ConstantContext.new(exp, @contexts.last))
|
118
|
+
end
|
119
|
+
|
116
120
|
def process_default(exp, context = nil)
|
117
121
|
@contexts.push(context) if context
|
118
122
|
@contexts.each do |c|
|
@@ -120,27 +124,25 @@ module Simplabs
|
|
120
124
|
c.send(method, exp) if c.respond_to?(method)
|
121
125
|
end
|
122
126
|
exp.children.each { |sub| process(sub) }
|
123
|
-
apply_checks(exp)
|
127
|
+
apply_checks(exp.file, context) if context
|
124
128
|
@contexts.pop if context
|
125
129
|
exp
|
126
130
|
end
|
127
131
|
|
128
132
|
private
|
129
133
|
|
130
|
-
def apply_checks(
|
131
|
-
|
132
|
-
|
133
|
-
checks.each { |check| check.evaluate_node(@contexts.last) if check.interesting_files.any? { |pattern| File.basename(exp.file) =~ pattern } }
|
134
|
-
end
|
134
|
+
def apply_checks(file, context)
|
135
|
+
checks = @checks[context.class] || []
|
136
|
+
checks.each { |check| check.evaluate_context(@contexts.last) if check.interesting_files.any? { |pattern| File.basename(file) =~ pattern } }
|
135
137
|
end
|
136
138
|
|
137
139
|
def setup_checks(checks)
|
138
140
|
@checks = {}
|
139
141
|
checks.each do |check|
|
140
|
-
check.
|
141
|
-
@checks[
|
142
|
-
@checks[
|
143
|
-
@checks[
|
142
|
+
check.interesting_contexts.each do |context|
|
143
|
+
@checks[context] ||= []
|
144
|
+
@checks[context] << check
|
145
|
+
@checks[context].uniq!
|
144
146
|
end
|
145
147
|
end
|
146
148
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Simplabs
|
2
|
+
|
3
|
+
module Excellent
|
4
|
+
|
5
|
+
module Parsing
|
6
|
+
|
7
|
+
class GasgnContext < SexpContext #:nodoc:
|
8
|
+
|
9
|
+
def initialize(exp, parent)
|
10
|
+
super
|
11
|
+
@name = exp[1].to_s.sub(/^\$/, '')
|
12
|
+
@full_name = @name
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -91,7 +91,7 @@ module Simplabs
|
|
91
91
|
# 'Basket#add_product'.
|
92
92
|
def full_name
|
93
93
|
return @full_name if @full_name
|
94
|
-
return @name if
|
94
|
+
return @name if !@parent
|
95
95
|
"#{@parent.full_name}::#{@name}"
|
96
96
|
end
|
97
97
|
|
@@ -116,6 +116,15 @@ module Simplabs
|
|
116
116
|
found_assignment
|
117
117
|
end
|
118
118
|
|
119
|
+
def resolve_colon(exp)
|
120
|
+
scope = if exp[1].node_type == :colon2
|
121
|
+
resolve_colon(exp[1])
|
122
|
+
elsif exp[1].node_type == :const
|
123
|
+
exp[1][1]
|
124
|
+
end
|
125
|
+
"#{scope.to_s}::#{exp[2].to_s}"
|
126
|
+
end
|
127
|
+
|
119
128
|
end
|
120
129
|
|
121
130
|
end
|
@@ -46,7 +46,7 @@ module Simplabs
|
|
46
46
|
end
|
47
47
|
task name do
|
48
48
|
paths = @paths.join(' ')
|
49
|
-
format = @html ? "
|
49
|
+
format = @html ? " -o #{@html}" : ''
|
50
50
|
system("excellent#{format} #{paths}")
|
51
51
|
$stdout.puts("\nWrote Excellent result to #{@html}\n\n") if @html
|
52
52
|
end
|
@@ -45,7 +45,7 @@ describe Simplabs::Excellent::Checks::Rails::ValidationsCheck do
|
|
45
45
|
warnings.should be_empty
|
46
46
|
end
|
47
47
|
|
48
|
-
%(validate validate_on_create validate_on_update).each do |method|
|
48
|
+
%w(validate validate_on_create validate_on_update).each do |method|
|
49
49
|
|
50
50
|
it "should accept an active record model that validates attribute by overriding #{method}" do
|
51
51
|
code = <<-END
|
metadata
CHANGED
@@ -1,56 +1,45 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: excellent
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.6.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- Marco Otte-Witte
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2009-08-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: ruby_parser
|
16
|
+
requirement: &70159583025320 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.0'
|
17
22
|
type: :runtime
|
18
|
-
|
19
|
-
version_requirements:
|
20
|
-
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: "2.0"
|
24
|
-
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70159583025320
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
26
|
name: sexp_processor
|
27
|
+
requirement: &70159583024300 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
27
33
|
type: :runtime
|
28
|
-
|
29
|
-
version_requirements:
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: "3.0"
|
34
|
-
version:
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: facets
|
37
|
-
type: :runtime
|
38
|
-
version_requirement:
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
requirements:
|
41
|
-
- - ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: "2.7"
|
44
|
-
version:
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70159583024300
|
45
36
|
description:
|
46
37
|
email: marco.otte-witte@simplabs.com
|
47
|
-
executables:
|
38
|
+
executables:
|
48
39
|
- excellent
|
49
40
|
extensions: []
|
50
|
-
|
51
41
|
extra_rdoc_files: []
|
52
|
-
|
53
|
-
files:
|
42
|
+
files:
|
54
43
|
- History.txt
|
55
44
|
- README.rdoc
|
56
45
|
- VERSION.yml
|
@@ -104,11 +93,13 @@ files:
|
|
104
93
|
- lib/simplabs/excellent/parsing/class_context.rb
|
105
94
|
- lib/simplabs/excellent/parsing/code_processor.rb
|
106
95
|
- lib/simplabs/excellent/parsing/conditional_context.rb
|
96
|
+
- lib/simplabs/excellent/parsing/constant_context.rb
|
107
97
|
- lib/simplabs/excellent/parsing/cvar_context.rb
|
108
98
|
- lib/simplabs/excellent/parsing/cyclomatic_complexity_measure.rb
|
109
99
|
- lib/simplabs/excellent/parsing/flog_measure.rb
|
110
100
|
- lib/simplabs/excellent/parsing/for_loop_context.rb
|
111
101
|
- lib/simplabs/excellent/parsing/gvar_context.rb
|
102
|
+
- lib/simplabs/excellent/parsing/gasgn_context.rb
|
112
103
|
- lib/simplabs/excellent/parsing/if_context.rb
|
113
104
|
- lib/simplabs/excellent/parsing/ivar_context.rb
|
114
105
|
- lib/simplabs/excellent/parsing/method_context.rb
|
@@ -156,34 +147,30 @@ files:
|
|
156
147
|
- spec/checks/singleton_variable_check_spec.rb
|
157
148
|
- spec/extensions/string_spec.rb
|
158
149
|
- spec/spec_helper.rb
|
159
|
-
has_rdoc: true
|
160
150
|
homepage: http://github.com/simplabs/excellent
|
161
151
|
licenses: []
|
162
|
-
|
163
152
|
post_install_message:
|
164
|
-
rdoc_options:
|
153
|
+
rdoc_options:
|
165
154
|
- --inline-source
|
166
155
|
- --charset=UTF-8
|
167
|
-
require_paths:
|
156
|
+
require_paths:
|
168
157
|
- lib
|
169
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
none: false
|
166
|
+
requirements:
|
167
|
+
- - ! '>='
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
181
170
|
requirements: []
|
182
|
-
|
183
171
|
rubyforge_project:
|
184
|
-
rubygems_version: 1.
|
172
|
+
rubygems_version: 1.8.11
|
185
173
|
signing_key:
|
186
174
|
specification_version: 2
|
187
175
|
summary: Source Code analysis gem for Ruby and Rails
|
188
176
|
test_files: []
|
189
|
-
|