simplabs-excellent 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ = 1.5.2
2
+
3
+ * added GlobalVariableCheck
4
+ * added Rails::CustomInitializeMethodCheck
5
+ * added Rails::ParamsHashInViewCheck
6
+ * added Rails::SessionHashInViewCheck
7
+
1
8
  = 1.5.1
2
9
 
3
10
  * removed duplication checks (they are just too coarse for dynamic languages like Ruby and especially Rails apps where you would call e.g. params all over the place)
data/README.rdoc CHANGED
@@ -3,6 +3,7 @@
3
3
  Excellent detects commonly regarded bad code snippets like empty +rescue+ blocks etc. It combines roodi (http://github.com/martinjandrews/roodi), most checks of reek (http://github.com/kevinrutherford/reek), flog (http://github.com/seattlerb/flog) and also adds some Rails specific checks.
4
4
 
5
5
  See the API documentation at http://docs.github.com/simplabs/excellent and the WIKI at http://wiki.github.com/simplabs/excellent.
6
+ Join the Google Group and discuss about the future and possibilities of Excellent: http://groups.google.com/group/excellent-gem.
6
7
 
7
8
  == Installation
8
9
 
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
3
  :minor: 5
4
- :patch: 1
4
+ :patch: 2
@@ -15,6 +15,7 @@ require 'simplabs/excellent/checks/case_missing_else_check'
15
15
  require 'simplabs/excellent/checks/class_line_count_check'
16
16
  require 'simplabs/excellent/checks/class_name_check'
17
17
  require 'simplabs/excellent/checks/singleton_variable_check'
18
+ require 'simplabs/excellent/checks/global_variable_check'
18
19
  require 'simplabs/excellent/checks/control_coupling_check'
19
20
  require 'simplabs/excellent/checks/cyclomatic_complexity_block_check'
20
21
  require 'simplabs/excellent/checks/cyclomatic_complexity_method_check'
@@ -0,0 +1,33 @@
1
+ require 'simplabs/excellent/checks/base'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Checks
8
+
9
+ # This check reports global variables. Global variables introduce strong dependencies between otherwise unrelated parts of code and their use is
10
+ # usually considered extremely bad style.
11
+ #
12
+ # ==== Applies to
13
+ #
14
+ # * global variables
15
+ class GlobalVariableCheck < Base
16
+
17
+ def initialize #:nodoc:
18
+ super
19
+ @interesting_nodes = [:gvar, :gasgn]
20
+ @interesting_files = [/\.rb$/, /\.erb$/]
21
+ end
22
+
23
+ def evaluate(context) #:nodoc:
24
+ add_warning(context, 'Global variable {{variable}} used.', { :variable => context.full_name })
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -17,3 +17,6 @@ require 'simplabs/excellent/checks/rails/attr_accessible_check'
17
17
  require 'simplabs/excellent/checks/rails/attr_protected_check'
18
18
  require 'simplabs/excellent/checks/rails/instance_var_in_partial_check'
19
19
  require 'simplabs/excellent/checks/rails/validations_check'
20
+ require 'simplabs/excellent/checks/rails/params_hash_in_view_check'
21
+ require 'simplabs/excellent/checks/rails/session_hash_in_view_check'
22
+ require 'simplabs/excellent/checks/rails/custom_initialize_method_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 +ActiveRecord+ models that define a custom +initialize+ method. Since +ActiveRecord+ does not always call +new+ to
12
+ # create instances, these custom +initialize+ methods might not always be called, which makes the behavior of the application very hard to
13
+ # understand.
14
+ #
15
+ # ==== Applies to
16
+ #
17
+ # * +ActiveRecord+ models
18
+ class CustomInitializeMethodCheck < Base
19
+
20
+ def initialize #:nodoc:
21
+ super
22
+ @interesting_nodes = [:class]
23
+ end
24
+
25
+ def evaluate(context) #:nodoc:
26
+ add_warning(context, '{{class}} defines initialize method.', { :class => context.full_name }) if context.active_record_model? && !context.defines_initializer?
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -13,7 +13,7 @@ module Simplabs
13
13
  #
14
14
  # ==== Applies to
15
15
  #
16
- # * instance variables
16
+ # * partials
17
17
  class InstanceVarInPartialCheck < Base
18
18
 
19
19
  def initialize #:nodoc:
@@ -0,0 +1,38 @@
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 views (and partials) that access the +params+ hash. Accessing the +params+ hash directly in views can result in security
12
+ # problems if the value is printed to the HTML output and in general is a bad habit because the controller, which is actually the part of the
13
+ # application that is responsible for dealing with parameters, is circumvented.
14
+ #
15
+ # ==== Applies to
16
+ #
17
+ # * partials and regular views
18
+ class ParamsHashInViewCheck < Base
19
+
20
+ def initialize #:nodoc:
21
+ super
22
+ @interesting_nodes = [:call]
23
+ @interesting_files = [/^.*\.(erb|rhtml)$/]
24
+ end
25
+
26
+ def evaluate(context) #:nodoc:
27
+ add_warning(context, 'Params hash used in view.') if (context.full_name == 'params')
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,38 @@
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 views (and partials) that access the +session+ hash. Accessing the +session+ hash directly in views can result in security
12
+ # problems if the value is printed to the HTML output and in general is a bad habit because the controller, which is actually the part of the
13
+ # application that is responsible for dealing with session data, is circumvented.
14
+ #
15
+ # ==== Applies to
16
+ #
17
+ # * partials and regular views
18
+ class SessionHashInViewCheck < Base
19
+
20
+ def initialize #:nodoc:
21
+ super
22
+ @interesting_nodes = [:call]
23
+ @interesting_files = [/^.*\.(erb|rhtml)$/]
24
+ end
25
+
26
+ def evaluate(context) #:nodoc:
27
+ add_warning(context, 'Session hash used in view.') if (context.full_name == 'session')
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -39,6 +39,7 @@ module Simplabs
39
39
  @line_count = count_lines
40
40
  @attr_accessible = false
41
41
  @attr_protected = false
42
+ @initializer = false
42
43
  @validations = []
43
44
  end
44
45
 
@@ -54,6 +55,10 @@ module Simplabs
54
55
  @attr_protected
55
56
  end
56
57
 
58
+ def defines_initializer?
59
+ @initializer
60
+ end
61
+
57
62
  def validating?
58
63
  !@validations.empty? || @methods.any?{ |method| %(validate validate_on_create validate_on_update).include?(method.name) }
59
64
  end
@@ -64,6 +69,11 @@ module Simplabs
64
69
  super
65
70
  end
66
71
 
72
+ def process_defn(exp)
73
+ @initializer = true if exp[2] == :initialize
74
+ super
75
+ end
76
+
67
77
  private
68
78
 
69
79
  def get_base_class_name
@@ -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/gvar_context'
14
15
  require 'simplabs/excellent/parsing/ivar_context'
15
16
  require 'simplabs/excellent/parsing/resbody_context'
16
17
  require 'simplabs/excellent/parsing/call_context'
@@ -62,6 +63,14 @@ module Simplabs
62
63
  process_default(exp, CvarContext.new(exp, @contexts.last))
63
64
  end
64
65
 
66
+ def process_gvar(exp)
67
+ process_default(exp, GvarContext.new(exp, @contexts.last))
68
+ end
69
+
70
+ def process_gasgn(exp)
71
+ process_default(exp, GvarContext.new(exp, @contexts.last))
72
+ end
73
+
65
74
  def process_if(exp)
66
75
  process_default(exp, IfContext.new(exp, @contexts.last))
67
76
  end
@@ -0,0 +1,21 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ class GvarContext < 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
@@ -12,27 +12,31 @@ 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' => { },
34
- :'Rails::InstanceVarInPartialCheck' => { },
35
- :'Rails::ValidationsCheck' => { }
15
+ :AssignmentInConditionalCheck => { },
16
+ :CaseMissingElseCheck => { },
17
+ :ClassLineCountCheck => { :threshold => 300 },
18
+ :ClassNameCheck => { :pattern => /^[A-Z][a-zA-Z0-9]*$/ },
19
+ :SingletonVariableCheck => { },
20
+ :GlobalVariableCheck => { },
21
+ :CyclomaticComplexityBlockCheck => { :complexity => 4 },
22
+ :CyclomaticComplexityMethodCheck => { :complexity => 8 },
23
+ :EmptyRescueBodyCheck => { },
24
+ :ForLoopCheck => { },
25
+ :MethodLineCountCheck => { :line_count => 20 },
26
+ :MethodNameCheck => { :pattern => /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ },
27
+ :ModuleLineCountCheck => { :line_count => 300 },
28
+ :ModuleNameCheck => { :pattern => /^[A-Z][a-zA-Z0-9]*$/ },
29
+ :ParameterNumberCheck => { :parameter_count => 3 },
30
+ :FlogMethodCheck => { },
31
+ :FlogBlockCheck => { },
32
+ :FlogClassCheck => { },
33
+ :'Rails::AttrProtectedCheck' => { },
34
+ :'Rails::AttrAccessibleCheck' => { },
35
+ :'Rails::InstanceVarInPartialCheck' => { },
36
+ :'Rails::ValidationsCheck' => { },
37
+ :'Rails::ParamsHashInViewCheck' => { },
38
+ :'Rails::SessionHashInViewCheck' => { },
39
+ :'Rails::CustomInitializeMethodCheck' => { }
36
40
  }
37
41
 
38
42
  attr_accessor :config #:nodoc:
@@ -0,0 +1,66 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::GlobalVariableCheck do
4
+
5
+ before(:each) do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::GlobalVariableCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should reject global variables' do
12
+ code = <<-END
13
+ $foo = 'bar'
14
+ END
15
+ @excellent.check_code(code)
16
+ warnings = @excellent.warnings
17
+
18
+ warnings.should_not be_empty
19
+ warnings[0].info.should == { :variable => 'foo' }
20
+ warnings[0].line_number.should == 1
21
+ warnings[0].message.should == 'Global variable foo used.'
22
+ end
23
+
24
+ it 'should also work in modules' do
25
+ code = <<-END
26
+ module Outer
27
+ module Inner
28
+ class Class
29
+ $foo = 'bar'
30
+ end
31
+ end
32
+ end
33
+ END
34
+ @excellent.check_code(code)
35
+ warnings = @excellent.warnings
36
+
37
+ warnings.should_not be_empty
38
+ warnings[0].info.should == { :variable => 'foo' }
39
+ warnings[0].line_number.should == 4
40
+ warnings[0].message.should == 'Global variable foo used.'
41
+ end
42
+
43
+ it 'should also work for global variables that occur within methods' do
44
+ code = <<-END
45
+ module Outer
46
+ module Inner
47
+ class Class
48
+ def method
49
+ $foo == 'bar'
50
+ end
51
+ end
52
+ end
53
+ end
54
+ END
55
+ @excellent.check_code(code)
56
+ warnings = @excellent.warnings
57
+
58
+ warnings.should_not be_empty
59
+ warnings[0].info.should == { :variable => 'foo' }
60
+ warnings[0].line_number.should == 5
61
+ warnings[0].message.should == 'Global variable foo used.'
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,58 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::Rails::CustomInitializeMethodCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::Rails::CustomInitializeMethodCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should ignore classes that are not active record models' do
12
+ code = <<-END
13
+ class Test
14
+ def initialize
15
+ end
16
+ end
17
+ END
18
+ @excellent.check_code(code)
19
+ warnings = @excellent.warnings
20
+
21
+ warnings.should be_empty
22
+ end
23
+
24
+ it 'should reject an active record model that defines initialize' do
25
+ code = <<-END
26
+ class User < ActiveRecord::Base
27
+ def initialize
28
+ end
29
+ end
30
+ END
31
+ @excellent.check_code(code)
32
+ warnings = @excellent.warnings
33
+
34
+ warnings.should_not be_empty
35
+ warnings[0].info.should == { :class => 'User' }
36
+ warnings[0].line_number.should == 1
37
+ warnings[0].message.should == 'User defines initialize method.'
38
+ end
39
+
40
+ it 'should also work with namespaced models' do
41
+ code = <<-END
42
+ class Backend::User < ActiveRecord::Base
43
+ def initialize
44
+ end
45
+ end
46
+ END
47
+ @excellent.check_code(code)
48
+ warnings = @excellent.warnings
49
+
50
+ warnings.should_not be_empty
51
+ warnings[0].info.should == { :class => 'Backend::User' }
52
+ warnings[0].line_number.should == 1
53
+ warnings[0].message.should == 'Backend::User defines initialize method.'
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::Rails::ParamsHashInViewCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::Rails::ParamsHashInViewCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should accept views that do not use the params hash' 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 views that use the params hash' do
24
+ code = <<-END
25
+ <div>
26
+ <%= params[:q] %>
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 == {}
34
+ warnings[0].line_number.should == 2
35
+ warnings[0].message.should == 'Params hash used in view.'
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::Rails::SessionHashInViewCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::Rails::SessionHashInViewCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should accept views that do not use the session hash' 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 views that use the session hash' do
24
+ code = <<-END
25
+ <div>
26
+ <%= session[:someCount] %>
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 == {}
34
+ warnings[0].line_number.should == 2
35
+ warnings[0].message.should == 'Session hash used in view.'
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.5.1
4
+ version: 1.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Otte-Witte
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-06 00:00:00 -07:00
12
+ date: 2009-08-05 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -61,6 +61,7 @@ files:
61
61
  - lib/simplabs/excellent/checks/flog_class_check.rb
62
62
  - lib/simplabs/excellent/checks/flog_method_check.rb
63
63
  - lib/simplabs/excellent/checks/for_loop_check.rb
64
+ - lib/simplabs/excellent/checks/global_variable_check.rb
64
65
  - lib/simplabs/excellent/checks/line_count_check.rb
65
66
  - lib/simplabs/excellent/checks/method_line_count_check.rb
66
67
  - lib/simplabs/excellent/checks/method_name_check.rb
@@ -71,7 +72,10 @@ files:
71
72
  - lib/simplabs/excellent/checks/parameter_number_check.rb
72
73
  - lib/simplabs/excellent/checks/rails/attr_accessible_check.rb
73
74
  - lib/simplabs/excellent/checks/rails/attr_protected_check.rb
75
+ - lib/simplabs/excellent/checks/rails/custom_initialize_method_check.rb
74
76
  - lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb
77
+ - lib/simplabs/excellent/checks/rails/params_hash_in_view_check.rb
78
+ - lib/simplabs/excellent/checks/rails/session_hash_in_view_check.rb
75
79
  - lib/simplabs/excellent/checks/rails/validations_check.rb
76
80
  - lib/simplabs/excellent/checks/rails.rb
77
81
  - lib/simplabs/excellent/checks/singleton_variable_check.rb
@@ -94,6 +98,7 @@ files:
94
98
  - lib/simplabs/excellent/parsing/cyclomatic_complexity_measure.rb
95
99
  - lib/simplabs/excellent/parsing/flog_measure.rb
96
100
  - lib/simplabs/excellent/parsing/for_loop_context.rb
101
+ - lib/simplabs/excellent/parsing/gvar_context.rb
97
102
  - lib/simplabs/excellent/parsing/if_context.rb
98
103
  - lib/simplabs/excellent/parsing/ivar_context.rb
99
104
  - lib/simplabs/excellent/parsing/method_context.rb
@@ -124,6 +129,7 @@ files:
124
129
  - spec/checks/flog_class_check_spec.rb
125
130
  - spec/checks/flog_method_check_spec.rb
126
131
  - spec/checks/for_loop_check_spec.rb
132
+ - spec/checks/global_variable_check_spec.rb
127
133
  - spec/checks/method_line_count_check_spec.rb
128
134
  - spec/checks/method_name_check_spec.rb
129
135
  - spec/checks/module_line_count_check_spec.rb
@@ -132,13 +138,17 @@ files:
132
138
  - spec/checks/parameter_number_check_spec.rb
133
139
  - spec/checks/rails/attr_accessible_check_spec.rb
134
140
  - spec/checks/rails/attr_protected_check_spec.rb
141
+ - spec/checks/rails/custom_initialize_method_check_spec.rb
135
142
  - spec/checks/rails/instance_var_in_partial_check_spec.rb
143
+ - spec/checks/rails/params_hash_in_view_check_spec.rb
144
+ - spec/checks/rails/session_hash_in_view_check_spec.rb
136
145
  - spec/checks/rails/validations_check_spec.rb
137
146
  - spec/checks/singleton_variable_check_spec.rb
138
147
  - spec/extensions/string_spec.rb
139
148
  - spec/spec_helper.rb
140
149
  has_rdoc: true
141
150
  homepage: http://github.com/simplabs/excellent
151
+ licenses:
142
152
  post_install_message:
143
153
  rdoc_options:
144
154
  - --inline-source
@@ -160,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
170
  requirements: []
161
171
 
162
172
  rubyforge_project:
163
- rubygems_version: 1.2.0
173
+ rubygems_version: 1.3.5
164
174
  signing_key:
165
175
  specification_version: 2
166
176
  summary: Source Code analysis gem for Ruby and Rails