excellent 1.5.4 → 1.6.0
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/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
|
-
|