simplabs-excellent 1.3.1 → 1.4.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 CHANGED
@@ -1,3 +1,8 @@
1
+ = 1.4.0
2
+
3
+ * Excellent not parses *.erb files
4
+ * added new check InstanceVarInPartialCheck
5
+
1
6
  = 1.3.1
2
7
 
3
8
  * FIX (forgot files in gemspec on 1.3.0)
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
- :minor: 3
4
- :patch: 1
3
+ :minor: 4
4
+ :patch: 0
@@ -9,7 +9,7 @@ module Simplabs #:nodoc:
9
9
 
10
10
  module Excellent #:nodoc:
11
11
 
12
- VERSION = '1.3.1'
12
+ VERSION = '1.4.0'
13
13
 
14
14
  end
15
15
 
@@ -23,6 +23,7 @@ module Simplabs
23
23
  def initialize(options = {}) #:nodoc:
24
24
  super()
25
25
  @interesting_nodes = [:if, :while, :until]
26
+ @interesting_files = [/\.rb$/, /\.erb$/]
26
27
  end
27
28
 
28
29
  def evaluate(context) #:nodoc:
@@ -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).
@@ -18,6 +18,7 @@ module Simplabs
18
18
  def initialize #:nodoc:
19
19
  super
20
20
  @interesting_nodes = [:case]
21
+ @interesting_files = [/\.rb$/, /\.erb$/]
21
22
  end
22
23
 
23
24
  def evaluate(context) #:nodoc:
@@ -26,6 +26,7 @@ module Simplabs
26
26
  def initialize #:nodoc:
27
27
  super
28
28
  @interesting_nodes = [:for]
29
+ @interesting_files = [/\.rb$/, /\.erb$/]
29
30
  end
30
31
 
31
32
  def evaluate(context) #:nodoc:
@@ -16,6 +16,7 @@ module Simplabs
16
16
  def initialize #:nodoc:
17
17
  super
18
18
  @interesting_nodes = [:iter]
19
+ @interesting_files = [/\.rb$/, /\.erb$/]
19
20
  end
20
21
 
21
22
  def evaluate(context) #:nodoc:
@@ -15,3 +15,4 @@ end
15
15
 
16
16
  require 'simplabs/excellent/checks/rails/attr_accessible_check'
17
17
  require 'simplabs/excellent/checks/rails/attr_protected_check'
18
+ require 'simplabs/excellent/checks/rails/instance_var_in_partial_check'
@@ -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
@@ -17,6 +17,7 @@ module Simplabs
17
17
  def initialize #:nodoc:
18
18
  super
19
19
  @interesting_nodes = [:cvar]
20
+ @interesting_files = [/\.rb$/, /\.erb$/]
20
21
  end
21
22
 
22
23
  def evaluate(context) #:nodoc:
@@ -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) } unless checks.nil?
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 => { :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' => { }
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.3.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