simplabs-excellent 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/VERSION.yml +2 -2
- data/lib/simplabs/excellent.rb +1 -1
- data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +1 -0
- data/lib/simplabs/excellent/checks/base.rb +8 -1
- data/lib/simplabs/excellent/checks/case_missing_else_check.rb +1 -0
- data/lib/simplabs/excellent/checks/for_loop_check.rb +1 -0
- data/lib/simplabs/excellent/checks/nested_iterators_check.rb +1 -0
- data/lib/simplabs/excellent/checks/rails.rb +1 -0
- data/lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb +37 -0
- data/lib/simplabs/excellent/checks/singleton_variable_check.rb +1 -0
- data/lib/simplabs/excellent/formatters/html.rb +21 -0
- data/lib/simplabs/excellent/parsing/code_processor.rb +7 -2
- data/lib/simplabs/excellent/parsing/ivar_context.rb +32 -0
- data/lib/simplabs/excellent/parsing/parser.rb +2 -0
- data/lib/simplabs/excellent/runner.rb +21 -20
- data/spec/checks/rails/instance_var_in_partial_check_spec.rb +40 -0
- metadata +4 -1
data/History.txt
CHANGED
data/VERSION.yml
CHANGED
data/lib/simplabs/excellent.rb
CHANGED
@@ -16,8 +16,15 @@ module Simplabs
|
|
16
16
|
# e.g. <tt>:if</tt> or <tt>:defn</tt>
|
17
17
|
attr_reader :interesting_nodes
|
18
18
|
|
19
|
+
# An array of regular expressions for file names that are interesting for the check. These will usually be path extensions rather than longer
|
20
|
+
# patterns (e.g. *.rb as well as *.erb files or *.rb files only).
|
21
|
+
#
|
22
|
+
# Defaults to /\.rb$/. If you do not specify anything else in custom checks, only *.rb files will be processed
|
23
|
+
attr_reader :interesting_files
|
24
|
+
|
19
25
|
def initialize #:nodoc:
|
20
|
-
@warnings
|
26
|
+
@warnings = []
|
27
|
+
@interesting_files = [/\.rb$/]
|
21
28
|
end
|
22
29
|
|
23
30
|
# This method is called whenever Excellent processes a node that the check specified as one of the nodes it is interested in (see interesting_nodes).
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'simplabs/excellent/checks/base'
|
2
|
+
|
3
|
+
module Simplabs
|
4
|
+
|
5
|
+
module Excellent
|
6
|
+
|
7
|
+
module Checks
|
8
|
+
|
9
|
+
module Rails
|
10
|
+
|
11
|
+
# This check reports partials that use instance variables. Using instance variables in partials couples the partial to the controller action or
|
12
|
+
# template that includes the partial and that has to define the instance variable.
|
13
|
+
#
|
14
|
+
# ==== Applies to
|
15
|
+
#
|
16
|
+
# * instance variables
|
17
|
+
class InstanceVarInPartialCheck < Base
|
18
|
+
|
19
|
+
def initialize #:nodoc:
|
20
|
+
super
|
21
|
+
@interesting_nodes = [:ivar]
|
22
|
+
@interesting_files = [/^_.*\.erb$/]
|
23
|
+
end
|
24
|
+
|
25
|
+
def evaluate(context) #:nodoc:
|
26
|
+
add_warning(context, 'Instance variable {{variable}} used in partial.', { :variable => context.full_name })
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -91,6 +91,24 @@ module Simplabs
|
|
91
91
|
text-align: right;
|
92
92
|
display: inline-block;
|
93
93
|
}
|
94
|
+
|
95
|
+
#footer {
|
96
|
+
margin: 20px 0 20px 0;
|
97
|
+
padding: 5px;
|
98
|
+
text-align: center;
|
99
|
+
}
|
100
|
+
|
101
|
+
#footer a {
|
102
|
+
color: #000;
|
103
|
+
background-color: #ddd;
|
104
|
+
text-decoration: none;
|
105
|
+
padding: 0 2px 0 2px;
|
106
|
+
}
|
107
|
+
|
108
|
+
#footer a:active, #footer a:hover {
|
109
|
+
color: #fff;
|
110
|
+
background-color: #222;
|
111
|
+
}
|
94
112
|
</style>
|
95
113
|
</head>
|
96
114
|
<body>
|
@@ -119,6 +137,9 @@ module Simplabs
|
|
119
137
|
|
120
138
|
FOOTER_TEMPLATE = <<-END
|
121
139
|
</div>
|
140
|
+
<div id="footer">
|
141
|
+
<a href="http://github.com/simplabs/excellent" title="Excellent at github">Excellent</a> by <a href="http://simplabs.com" title="simplabs">simplabs</a>
|
142
|
+
</div>
|
122
143
|
</body>
|
123
144
|
</html>
|
124
145
|
END
|
@@ -11,6 +11,7 @@ require 'simplabs/excellent/parsing/for_loop_context'
|
|
11
11
|
require 'simplabs/excellent/parsing/while_context'
|
12
12
|
require 'simplabs/excellent/parsing/until_context'
|
13
13
|
require 'simplabs/excellent/parsing/cvar_context'
|
14
|
+
require 'simplabs/excellent/parsing/ivar_context'
|
14
15
|
require 'simplabs/excellent/parsing/resbody_context'
|
15
16
|
require 'simplabs/excellent/parsing/call_context'
|
16
17
|
|
@@ -53,6 +54,10 @@ module Simplabs
|
|
53
54
|
process_default(exp, SingletonMethodContext.new(exp, @contexts.last))
|
54
55
|
end
|
55
56
|
|
57
|
+
def process_ivar(exp)
|
58
|
+
process_default(exp, IvarContext.new(exp, @contexts.last))
|
59
|
+
end
|
60
|
+
|
56
61
|
def process_cvar(exp)
|
57
62
|
process_default(exp, CvarContext.new(exp, @contexts.last))
|
58
63
|
end
|
@@ -118,8 +123,8 @@ module Simplabs
|
|
118
123
|
|
119
124
|
def apply_checks(exp)
|
120
125
|
if exp.is_a?(Sexp)
|
121
|
-
checks = @checks[exp.node_type]
|
122
|
-
checks.each { |check| check.evaluate_node(@contexts.last)
|
126
|
+
checks = @checks[exp.node_type] || []
|
127
|
+
checks.each { |check| check.evaluate_node(@contexts.last) if check.interesting_files.any? { |pattern| File.basename(exp.file) =~ pattern } }
|
123
128
|
end
|
124
129
|
end
|
125
130
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Simplabs
|
2
|
+
|
3
|
+
module Excellent
|
4
|
+
|
5
|
+
module Parsing
|
6
|
+
|
7
|
+
class IvarContext < SexpContext #:nodoc:
|
8
|
+
|
9
|
+
def initialize(exp, parent)
|
10
|
+
super
|
11
|
+
@name = exp[1].to_s.sub(/^@+/, '')
|
12
|
+
end
|
13
|
+
|
14
|
+
def full_name
|
15
|
+
return @name if @parent.nil?
|
16
|
+
full_name = @name
|
17
|
+
parent = @parent
|
18
|
+
parent = parent.parent until parent.is_a?(ClassContext) || parent.is_a?(ModuleContext) || parent.nil?
|
19
|
+
if parent
|
20
|
+
full_name = "#{parent.full_name}.#{full_name}"
|
21
|
+
else
|
22
|
+
@name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'ruby_parser'
|
3
3
|
require 'facets'
|
4
|
+
require 'erb'
|
4
5
|
|
5
6
|
module Simplabs
|
6
7
|
|
@@ -22,6 +23,7 @@ module Simplabs
|
|
22
23
|
|
23
24
|
def silent_parse(content, filename)
|
24
25
|
@parser ||= RubyParser.new
|
26
|
+
content = ::ERB.new(content, nil, '-').src if filename =~ /\.erb$/
|
25
27
|
sexp = @parser.parse(content, filename)
|
26
28
|
sexp
|
27
29
|
end
|
@@ -12,25 +12,26 @@ module Simplabs
|
|
12
12
|
class Runner
|
13
13
|
|
14
14
|
DEFAULT_CONFIG = {
|
15
|
-
:AssignmentInConditionalCheck
|
16
|
-
:CaseMissingElseCheck
|
17
|
-
:ClassLineCountCheck
|
18
|
-
:ClassNameCheck
|
19
|
-
:SingletonVariableCheck
|
20
|
-
:CyclomaticComplexityBlockCheck
|
21
|
-
:CyclomaticComplexityMethodCheck
|
22
|
-
:EmptyRescueBodyCheck
|
23
|
-
:ForLoopCheck
|
24
|
-
:MethodLineCountCheck
|
25
|
-
:MethodNameCheck
|
26
|
-
:ModuleLineCountCheck
|
27
|
-
:ModuleNameCheck
|
28
|
-
:ParameterNumberCheck
|
29
|
-
:FlogMethodCheck
|
30
|
-
:FlogBlockCheck
|
31
|
-
:FlogClassCheck
|
32
|
-
:'Rails::AttrProtectedCheck'
|
33
|
-
:'Rails::AttrAccessibleCheck'
|
15
|
+
:AssignmentInConditionalCheck => { },
|
16
|
+
:CaseMissingElseCheck => { },
|
17
|
+
:ClassLineCountCheck => { :threshold => 300 },
|
18
|
+
:ClassNameCheck => { :pattern => /^[A-Z][a-zA-Z0-9]*$/ },
|
19
|
+
:SingletonVariableCheck => { },
|
20
|
+
:CyclomaticComplexityBlockCheck => { :complexity => 4 },
|
21
|
+
:CyclomaticComplexityMethodCheck => { :complexity => 8 },
|
22
|
+
:EmptyRescueBodyCheck => { },
|
23
|
+
:ForLoopCheck => { },
|
24
|
+
:MethodLineCountCheck => { :line_count => 20 },
|
25
|
+
:MethodNameCheck => { :pattern => /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ },
|
26
|
+
:ModuleLineCountCheck => { :line_count => 300 },
|
27
|
+
:ModuleNameCheck => { :pattern => /^[A-Z][a-zA-Z0-9]*$/ },
|
28
|
+
:ParameterNumberCheck => { :parameter_count => 3 },
|
29
|
+
:FlogMethodCheck => { },
|
30
|
+
:FlogBlockCheck => { },
|
31
|
+
:FlogClassCheck => { },
|
32
|
+
:'Rails::AttrProtectedCheck' => { },
|
33
|
+
:'Rails::AttrAccessibleCheck' => { },
|
34
|
+
:'Rails::InstanceVarInPartialCheck' => { }
|
34
35
|
}
|
35
36
|
|
36
37
|
attr_accessor :config #:nodoc:
|
@@ -119,7 +120,7 @@ module Simplabs
|
|
119
120
|
if File.file?(path)
|
120
121
|
files << path
|
121
122
|
elsif File.directory?(path)
|
122
|
-
files += Dir.glob(File.join(path, '**/*.rb'))
|
123
|
+
files += Dir.glob(File.join(path, '**/*.{rb,erb}'))
|
123
124
|
else
|
124
125
|
raise ArgumentError.new("#{path} is neither a File nor a directory!")
|
125
126
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Simplabs::Excellent::Checks::Rails::InstanceVarInPartialCheck do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::Rails::InstanceVarInPartialCheck.new)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#evaluate' do
|
10
|
+
|
11
|
+
it 'should accept partials that do not use instance variables' do
|
12
|
+
code = <<-END
|
13
|
+
<div>
|
14
|
+
<%= 'some text' %>
|
15
|
+
</div>
|
16
|
+
END
|
17
|
+
@excellent.check('_dummy-file.html.erb', code)
|
18
|
+
warnings = @excellent.warnings
|
19
|
+
|
20
|
+
warnings.should be_empty
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should reject partials that use instance variables' do
|
24
|
+
code = <<-END
|
25
|
+
<div>
|
26
|
+
<%= @ivar %>
|
27
|
+
</div>
|
28
|
+
END
|
29
|
+
@excellent.check('_dummy-file.html.erb', code)
|
30
|
+
warnings = @excellent.warnings
|
31
|
+
|
32
|
+
warnings.should_not be_empty
|
33
|
+
warnings[0].info.should == { :variable => 'ivar' }
|
34
|
+
warnings[0].line_number.should == 2
|
35
|
+
warnings[0].message.should == 'Instance variable ivar used in partial.'
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simplabs-excellent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marco Otte-Witte
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- lib/simplabs/excellent/checks/parameter_number_check.rb
|
73
73
|
- lib/simplabs/excellent/checks/rails/attr_accessible_check.rb
|
74
74
|
- lib/simplabs/excellent/checks/rails/attr_protected_check.rb
|
75
|
+
- lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb
|
75
76
|
- lib/simplabs/excellent/checks/rails.rb
|
76
77
|
- lib/simplabs/excellent/checks/singleton_variable_check.rb
|
77
78
|
- lib/simplabs/excellent/checks.rb
|
@@ -94,6 +95,7 @@ files:
|
|
94
95
|
- lib/simplabs/excellent/parsing/flog_measure.rb
|
95
96
|
- lib/simplabs/excellent/parsing/for_loop_context.rb
|
96
97
|
- lib/simplabs/excellent/parsing/if_context.rb
|
98
|
+
- lib/simplabs/excellent/parsing/ivar_context.rb
|
97
99
|
- lib/simplabs/excellent/parsing/method_context.rb
|
98
100
|
- lib/simplabs/excellent/parsing/module_context.rb
|
99
101
|
- lib/simplabs/excellent/parsing/parser.rb
|
@@ -129,6 +131,7 @@ files:
|
|
129
131
|
- spec/checks/parameter_number_check_spec.rb
|
130
132
|
- spec/checks/rails/attr_accessible_check_spec.rb
|
131
133
|
- spec/checks/rails/attr_protected_check_spec.rb
|
134
|
+
- spec/checks/rails/instance_var_in_partial_check_spec.rb
|
132
135
|
- spec/checks/singleton_variable_check_spec.rb
|
133
136
|
- spec/extensions/string_spec.rb
|
134
137
|
- spec/spec_helper.rb
|