simplabs-excellent 1.5.1 → 1.5.2

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,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