excellent 1.7.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/History.txt +9 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +123 -0
  4. data/bin/excellent +49 -12
  5. data/lib/simplabs/excellent.rb +2 -2
  6. data/lib/simplabs/excellent/checks.rb +1 -1
  7. data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +1 -1
  8. data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +1 -1
  9. data/lib/simplabs/excellent/checks/base.rb +12 -9
  10. data/lib/simplabs/excellent/checks/case_missing_else_check.rb +1 -1
  11. data/lib/simplabs/excellent/checks/class_line_count_check.rb +3 -3
  12. data/lib/simplabs/excellent/checks/class_name_check.rb +5 -5
  13. data/lib/simplabs/excellent/checks/{singleton_variable_check.rb → class_variable_check.rb} +3 -3
  14. data/lib/simplabs/excellent/checks/control_coupling_check.rb +1 -1
  15. data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +4 -4
  16. data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +3 -3
  17. data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +2 -2
  18. data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +1 -1
  19. data/lib/simplabs/excellent/checks/flog_block_check.rb +2 -2
  20. data/lib/simplabs/excellent/checks/flog_check.rb +3 -3
  21. data/lib/simplabs/excellent/checks/flog_class_check.rb +2 -2
  22. data/lib/simplabs/excellent/checks/flog_method_check.rb +2 -2
  23. data/lib/simplabs/excellent/checks/for_loop_check.rb +1 -1
  24. data/lib/simplabs/excellent/checks/global_variable_check.rb +5 -2
  25. data/lib/simplabs/excellent/checks/line_count_check.rb +3 -3
  26. data/lib/simplabs/excellent/checks/method_line_count_check.rb +2 -2
  27. data/lib/simplabs/excellent/checks/method_name_check.rb +5 -4
  28. data/lib/simplabs/excellent/checks/module_line_count_check.rb +2 -2
  29. data/lib/simplabs/excellent/checks/module_name_check.rb +3 -3
  30. data/lib/simplabs/excellent/checks/name_check.rb +4 -4
  31. data/lib/simplabs/excellent/checks/nested_iterators_check.rb +2 -2
  32. data/lib/simplabs/excellent/checks/parameter_number_check.rb +1 -1
  33. data/lib/simplabs/excellent/checks/rails/attr_accessible_check.rb +1 -1
  34. data/lib/simplabs/excellent/checks/rails/attr_protected_check.rb +1 -1
  35. data/lib/simplabs/excellent/checks/rails/custom_initialize_method_check.rb +1 -1
  36. data/lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb +1 -1
  37. data/lib/simplabs/excellent/checks/rails/params_hash_in_view_check.rb +1 -1
  38. data/lib/simplabs/excellent/checks/rails/session_hash_in_view_check.rb +1 -1
  39. data/lib/simplabs/excellent/checks/rails/validations_check.rb +1 -1
  40. data/lib/simplabs/excellent/formatters/text.rb +7 -1
  41. data/lib/simplabs/excellent/parsing/gvar_context.rb +0 -8
  42. data/lib/simplabs/excellent/parsing/loc_parser.rb +94 -0
  43. data/lib/simplabs/excellent/parsing/resbody_context.rb +0 -6
  44. data/lib/simplabs/excellent/runner.rb +49 -32
  45. data/lib/simplabs/excellent/warning.rb +1 -4
  46. metadata +23 -49
  47. data/README.rdoc +0 -72
  48. data/VERSION.yml +0 -4
  49. data/lib/simplabs/excellent/extensions/string.rb +0 -28
  50. data/spec/checks/abc_metric_method_check_spec.rb +0 -122
  51. data/spec/checks/assignment_in_conditional_check_spec.rb +0 -90
  52. data/spec/checks/case_missing_else_check_spec.rb +0 -46
  53. data/spec/checks/class_line_count_check_spec.rb +0 -62
  54. data/spec/checks/class_name_check_spec.rb +0 -48
  55. data/spec/checks/control_coupling_check_spec.rb +0 -103
  56. data/spec/checks/cyclomatic_complexity_block_check_spec.rb +0 -47
  57. data/spec/checks/cyclomatic_complexity_method_check_spec.rb +0 -210
  58. data/spec/checks/empty_rescue_body_check_spec.rb +0 -170
  59. data/spec/checks/flog_block_check_spec.rb +0 -28
  60. data/spec/checks/flog_class_check_spec.rb +0 -28
  61. data/spec/checks/flog_method_check_spec.rb +0 -46
  62. data/spec/checks/for_loop_check_spec.rb +0 -52
  63. data/spec/checks/global_variable_check_spec.rb +0 -66
  64. data/spec/checks/method_line_count_check_spec.rb +0 -49
  65. data/spec/checks/method_name_check_spec.rb +0 -112
  66. data/spec/checks/module_line_count_check_spec.rb +0 -48
  67. data/spec/checks/module_name_check_spec.rb +0 -61
  68. data/spec/checks/nested_iterators_check_spec.rb +0 -44
  69. data/spec/checks/parameter_number_check_spec.rb +0 -97
  70. data/spec/checks/rails/attr_accessible_check_spec.rb +0 -79
  71. data/spec/checks/rails/attr_protected_check_spec.rb +0 -77
  72. data/spec/checks/rails/custom_initialize_method_check_spec.rb +0 -58
  73. data/spec/checks/rails/instance_var_in_partial_check_spec.rb +0 -40
  74. data/spec/checks/rails/params_hash_in_view_check_spec.rb +0 -40
  75. data/spec/checks/rails/session_hash_in_view_check_spec.rb +0 -40
  76. data/spec/checks/rails/validations_check_spec.rb +0 -81
  77. data/spec/checks/singleton_variable_check_spec.rb +0 -66
  78. data/spec/extensions/string_spec.rb +0 -13
  79. data/spec/spec_helper.rb +0 -13
@@ -29,8 +29,8 @@ module Simplabs
29
29
  DEFAULT_THRESHOLD = 8
30
30
 
31
31
  def initialize(options = {}) #:nodoc:
32
- threshold = options[:threshold] || DEFAULT_THRESHOLD
33
- super([Parsing::MethodContext, Parsing::SingletonMethodContext], threshold)
32
+ options[:threshold] ||= DEFAULT_THRESHOLD
33
+ super([Parsing::MethodContext, Parsing::SingletonMethodContext], options)
34
34
  end
35
35
 
36
36
  def evaluate(context) #:nodoc:
@@ -13,7 +13,7 @@ module Simplabs
13
13
  # * +rescue+ blocks
14
14
  class EmptyRescueBodyCheck < Base
15
15
 
16
- def initialize #:nodoc:
16
+ def initialize(options = {}) #:nodoc:
17
17
  super
18
18
  @interesting_contexts = [Parsing::ResbodyContext]
19
19
  end
@@ -21,8 +21,8 @@ module Simplabs
21
21
  DEFAULT_THRESHOLD = 15
22
22
 
23
23
  def initialize(options = {}) #:nodoc:
24
- threshold = options[:threshold] || DEFAULT_THRESHOLD
25
- super([Parsing::BlockContext], threshold)
24
+ options[:threshold] ||= DEFAULT_THRESHOLD
25
+ super([Parsing::BlockContext], options)
26
26
  end
27
27
 
28
28
  protected
@@ -8,10 +8,10 @@ module Simplabs
8
8
 
9
9
  class FlogCheck < Base #:nodoc:
10
10
 
11
- def initialize(interesting_contexts, threshold)
12
- super()
11
+ def initialize(interesting_contexts, options = {}) #:nodoc:
12
+ super(options)
13
13
  @interesting_contexts = interesting_contexts
14
- @threshold = threshold
14
+ @threshold = options[:threshold].to_i
15
15
  end
16
16
 
17
17
  def evaluate(context)
@@ -21,8 +21,8 @@ module Simplabs
21
21
  DEFAULT_THRESHOLD = 300
22
22
 
23
23
  def initialize(options = {}) #:nodoc:
24
- threshold = options[:threshold] || DEFAULT_THRESHOLD
25
- super([Parsing::ClassContext], threshold)
24
+ options[:threshold] ||= DEFAULT_THRESHOLD
25
+ super([Parsing::ClassContext], options)
26
26
  end
27
27
 
28
28
  protected
@@ -21,8 +21,8 @@ module Simplabs
21
21
  DEFAULT_THRESHOLD = 30
22
22
 
23
23
  def initialize(options = {}) #:nodoc:
24
- threshold = options[:threshold] || DEFAULT_THRESHOLD
25
- super([Parsing::MethodContext, Parsing::SingletonMethodContext], threshold)
24
+ options[:threshold] ||= DEFAULT_THRESHOLD
25
+ super([Parsing::MethodContext, Parsing::SingletonMethodContext], options)
26
26
  end
27
27
 
28
28
  protected
@@ -23,7 +23,7 @@ module Simplabs
23
23
  # * +for+ loops
24
24
  class ForLoopCheck < Base
25
25
 
26
- def initialize #:nodoc:
26
+ def initialize(options = {}) #:nodoc:(options => {}) #:nodoc:
27
27
  super
28
28
  @interesting_contexts = [Parsing::ForLoopContext]
29
29
  @interesting_files = [/\.rb$/, /\.erb$/]
@@ -14,14 +14,17 @@ module Simplabs
14
14
  # * global variables
15
15
  class GlobalVariableCheck < Base
16
16
 
17
- def initialize #:nodoc:
17
+ DEFAULT_WHITELIST = %w(! @ & ` ' + \d+ ~ = / \ , ; \. < > _ 0 * $ ? : " DEBUG FILENAME LOAD_PATH stdin stdout stderr VERBOSE -0 -a -d -F -i -I -l -p -v)
18
+
19
+ def initialize(options = {}) #:nodoc:
18
20
  super
21
+ @whitelist = options[:whitelist] ||= DEFAULT_WHITELIST
19
22
  @interesting_contexts = [Parsing::GvarContext, Parsing::GasgnContext]
20
23
  @interesting_files = [/\.rb$/, /\.erb$/]
21
24
  end
22
25
 
23
26
  def evaluate(context) #:nodoc:
24
- if context.is_a?(Parsing::GasgnContext) || !context.reassigned_local_exception_var?
27
+ if context.is_a?(Parsing::GasgnContext) || !@whitelist.include?(context.full_name)
25
28
  add_warning(context, 'Global variable {{variable}} used.', { :variable => context.full_name })
26
29
  end
27
30
  end
@@ -8,10 +8,10 @@ module Simplabs
8
8
 
9
9
  class LineCountCheck < Base #:nodoc:
10
10
 
11
- def initialize(interesting_contexts, threshold)
12
- super()
11
+ def initialize(interesting_contexts, options = {}) #:nodoc:
12
+ super(options)
13
13
  @interesting_contexts = interesting_contexts
14
- @threshold = threshold
14
+ @threshold = options[:threshold].to_i
15
15
  end
16
16
 
17
17
  def evaluate(context)
@@ -17,8 +17,8 @@ module Simplabs
17
17
  DEFAULT_THRESHOLD = 20
18
18
 
19
19
  def initialize(options = {}) #:nodoc:
20
- threshold = options[:threshold] || DEFAULT_THRESHOLD
21
- super([Parsing::MethodContext], threshold)
20
+ options[:threshold] ||= DEFAULT_THRESHOLD
21
+ super([Parsing::MethodContext], options)
22
22
  end
23
23
 
24
24
  protected
@@ -16,12 +16,13 @@ module Simplabs
16
16
  # * methods
17
17
  class MethodNameCheck < NameCheck
18
18
 
19
- DEFAULT_PATTERN = /^[_a-z<>=\[|+-\/\*\~\%\&`\|\^]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
20
- WHITELIST = %w([] ! != !~ % & * ** + +@ - -@ / < << <= <=> == === =~ > >= >> ^ ` | ~)
19
+ DEFAULT_PATTERN = '^[_a-z<>=\[|+-\/\*\~\%\&`\|\^]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$'
20
+ DEFAULT_WHITELIST = %w([] ! != !~ % & * ** + +@ - -@ / < << <= <=> == === =~ > >= >> ^ ` | ~)
21
21
 
22
22
  def initialize(options = {}) #:nodoc:
23
- pattern = options['pattern'] || DEFAULT_PATTERN
24
- super([Parsing::MethodContext, Parsing::SingletonMethodContext], pattern, WHITELIST)
23
+ options[:pattern] ||= DEFAULT_PATTERN
24
+ options[:whitelist] ||= DEFAULT_WHITELIST
25
+ super([Parsing::MethodContext, Parsing::SingletonMethodContext], options)
25
26
  end
26
27
 
27
28
  protected
@@ -17,8 +17,8 @@ module Simplabs
17
17
  DEFAULT_THRESHOLD = 300
18
18
 
19
19
  def initialize(options = {}) #:nodoc:
20
- threshold = options[:threshold] || DEFAULT_THRESHOLD
21
- super([Parsing::ModuleContext], threshold)
20
+ options[:threshold] ||= DEFAULT_THRESHOLD
21
+ super([Parsing::ModuleContext], options)
22
22
  end
23
23
 
24
24
  protected
@@ -16,11 +16,11 @@ module Simplabs
16
16
  # * modules
17
17
  class ModuleNameCheck < NameCheck
18
18
 
19
- DEFAULT_PATTERN = /^[A-Z][a-zA-Z0-9]*$/
19
+ DEFAULT_PATTERN = '^[A-Z][a-zA-Z0-9]*$'
20
20
 
21
21
  def initialize(options = {}) #:nodoc:
22
- pattern = options['pattern'] || DEFAULT_PATTERN
23
- super([Parsing::ModuleContext], pattern)
22
+ options[:pattern] ||= DEFAULT_PATTERN
23
+ super([Parsing::ModuleContext], options)
24
24
  end
25
25
 
26
26
  protected
@@ -8,11 +8,11 @@ module Simplabs
8
8
 
9
9
  class NameCheck < Base #:nodoc:
10
10
 
11
- def initialize(interesting_contexts, pattern, whitelist = [])
12
- super()
11
+ def initialize(interesting_contexts, options = {}) #:nodoc:
12
+ super(options)
13
13
  @interesting_contexts = interesting_contexts
14
- @pattern = pattern
15
- @whitelist = whitelist
14
+ @pattern = Regexp.new(options[:pattern].to_s)
15
+ @whitelist = Array(options[:whitelist])
16
16
  end
17
17
 
18
18
  def evaluate(context)
@@ -6,14 +6,14 @@ module Simplabs
6
6
 
7
7
  module Checks
8
8
 
9
- # This check reports nested iterators. Nested iterators lead to introduce performance issues.
9
+ # This check reports nested iterators. Nested iterators may introduce performance issues.
10
10
  #
11
11
  # ==== Applies to
12
12
  #
13
13
  # * blocks
14
14
  class NestedIteratorsCheck < Base
15
15
 
16
- def initialize #:nodoc:
16
+ def initialize(options = {}) #:nodoc:
17
17
  super
18
18
  @interesting_contexts = [Parsing::BlockContext]
19
19
  @interesting_files = [/\.rb$/, /\.erb$/]
@@ -18,7 +18,7 @@ module Simplabs
18
18
  DEFAULT_THRESHOLD = 3
19
19
 
20
20
  def initialize(options = {}) #:nodoc:
21
- super()
21
+ super
22
22
  @threshold = options[:threshold] || DEFAULT_THRESHOLD
23
23
  @interesting_contexts = [Parsing::MethodContext, Parsing::SingletonMethodContext, Parsing::BlockContext]
24
24
  end
@@ -18,7 +18,7 @@ module Simplabs
18
18
  # * +ActiveRecord+ models
19
19
  class AttrAccessibleCheck < Base
20
20
 
21
- def initialize #:nodoc:
21
+ def initialize(options = {}) #:nodoc:
22
22
  super
23
23
  @interesting_contexts = [Parsing::ClassContext]
24
24
  end
@@ -19,7 +19,7 @@ module Simplabs
19
19
  # * +ActiveRecord+ models
20
20
  class AttrProtectedCheck < Base
21
21
 
22
- def initialize #:nodoc:
22
+ def initialize(options = {}) #:nodoc:
23
23
  super
24
24
  @interesting_contexts = [Parsing::ClassContext]
25
25
  end
@@ -17,7 +17,7 @@ module Simplabs
17
17
  # * +ActiveRecord+ models
18
18
  class CustomInitializeMethodCheck < Base
19
19
 
20
- def initialize #:nodoc:
20
+ def initialize(options = {}) #:nodoc:
21
21
  super
22
22
  @interesting_contexts = [Parsing::ClassContext]
23
23
  end
@@ -16,7 +16,7 @@ module Simplabs
16
16
  # * partials
17
17
  class InstanceVarInPartialCheck < Base
18
18
 
19
- def initialize #:nodoc:
19
+ def initialize(options = {}) #:nodoc:
20
20
  super
21
21
  @interesting_contexts = [Parsing::IvarContext]
22
22
  @interesting_files = [/^_.*\.erb$/]
@@ -17,7 +17,7 @@ module Simplabs
17
17
  # * partials and regular views
18
18
  class ParamsHashInViewCheck < Base
19
19
 
20
- def initialize #:nodoc:
20
+ def initialize(options = {}) #:nodoc:
21
21
  super
22
22
  @interesting_contexts = [Parsing::CallContext]
23
23
  @interesting_files = [/^.*\.(erb|rhtml)$/]
@@ -17,7 +17,7 @@ module Simplabs
17
17
  # * partials and regular views
18
18
  class SessionHashInViewCheck < Base
19
19
 
20
- def initialize #:nodoc:
20
+ def initialize(options = {}) #:nodoc:
21
21
  super
22
22
  @interesting_contexts = [Parsing::CallContext]
23
23
  @interesting_files = [/^.*\.(erb|rhtml|haml)$/]
@@ -16,7 +16,7 @@ module Simplabs
16
16
  # * +ActiveRecord+ models
17
17
  class ValidationsCheck < Base
18
18
 
19
- def initialize #:nodoc:
19
+ def initialize(options = {}) #:nodoc:
20
20
  super
21
21
  @interesting_contexts = [Parsing::ClassContext]
22
22
  end
@@ -23,7 +23,7 @@ module Simplabs
23
23
  end
24
24
 
25
25
  def warning(warning)
26
- @stream.puts " * Line #{warning.line_number.to_s.lpad(3)}: \e[33m#{warning.message}\e[0m"
26
+ @stream.puts " * Line #{lpad(warning.line_number.to_s, 3)}: \e[33m#{warning.message}\e[0m"
27
27
  @total_warnings += 1
28
28
  end
29
29
 
@@ -31,6 +31,12 @@ module Simplabs
31
31
  @stream.puts "\n Found #{@total_warnings} warnings.\n\n"
32
32
  end
33
33
 
34
+ private
35
+
36
+ def lpad(string, length, fill = ' ')
37
+ [fill * ([length - string.length, 0].max), string].join
38
+ end
39
+
34
40
  end
35
41
 
36
42
  end
@@ -12,14 +12,6 @@ module Simplabs
12
12
  @full_name = @name
13
13
  end
14
14
 
15
- def reassigned_local_exception_var?
16
- if self.parent.is_a?(Simplabs::Excellent::Parsing::ResbodyContext)
17
- @name == '!' && self.parent.assigns_exception_to_local_variable?.inspect
18
- else
19
- false
20
- end
21
- end
22
-
23
15
  end
24
16
 
25
17
  end
@@ -0,0 +1,94 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ # Parser that counts the different types of lines for the given set of files.
8
+ #
9
+ class LOCParser
10
+
11
+ # The files to count the lines for
12
+ #
13
+ attr_accessor :files
14
+
15
+ def initialize(files) #:nodoc:
16
+ @files = collect_files(files)
17
+ end
18
+
19
+ # Returns a hash with file name as key and a hash of counts as value.
20
+ #
21
+ # { file => { :total => 9, :code => 3, ... }, ... }
22
+ #
23
+ # ==== Parameters
24
+ #
25
+ # * <tt>force</tt> - The count is cached once it was calculated. Specify +force+ to force recalculation.
26
+ def count(force = false)
27
+ @count = recount if @count.nil? || force
28
+ end
29
+
30
+ private
31
+
32
+ def recount
33
+ count = {}
34
+ files.each do |file|
35
+ total, code, comment, blank = *line_count(file)
36
+ count[file] = {
37
+ :total => total,
38
+ :code => code,
39
+ :comment => comment,
40
+ :blank => blank
41
+ }
42
+ end
43
+ count
44
+ end
45
+
46
+ def line_count(file)
47
+ total, code, comment = 0, 0, 0
48
+ in_block_comment = false
49
+ File.open(file) do |file|
50
+ while line = file.gets
51
+ total += 1
52
+ case line
53
+ when /^\s*$/
54
+ comment += 1 if in_block_comment
55
+ next
56
+ when /^=begin/
57
+ in_block_comment = true
58
+ comment += 1
59
+ when /^=end/
60
+ comment += 1
61
+ in_block_comment = false
62
+ when /^\s*#/
63
+ comment += 1
64
+ else
65
+ code += 1 if !in_block_comment
66
+ comment += 1 if in_block_comment
67
+ end
68
+ end
69
+ end
70
+ blank = total - code - comment
71
+ return total, code, comment, blank
72
+ end
73
+
74
+ def collect_files(paths)
75
+ files = []
76
+ paths.each do |path|
77
+ if File.file?(path)
78
+ files << path
79
+ elsif File.directory?(path)
80
+ files += Dir.glob(File.join(path, '**/*.{rb}')) # TODO: erb support ?
81
+ else
82
+ raise ArgumentError.new("#{path} is neither a file or a directory!")
83
+ end
84
+ end
85
+ files
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ end
93
+
94
+ end
@@ -17,12 +17,6 @@ module Simplabs
17
17
  @contains_statements
18
18
  end
19
19
 
20
- def assigns_exception_to_local_variable?
21
- @exp[1][2].node_type == :lasgn && @exp[1][2][2].to_a == [:gvar, :$!]
22
- rescue
23
- false
24
- end
25
-
26
20
  private
27
21
 
28
22
  def contains_statements?(exp = @exp)
@@ -11,38 +11,50 @@ module Simplabs
11
11
  # name of a file to read the code to process from.
12
12
  class Runner
13
13
 
14
- DEFAULT_CONFIG = {
15
- :AssignmentInConditionalCheck => { },
16
- :CaseMissingElseCheck => { },
17
- :ClassLineCountCheck => { :threshold => 300 },
18
- :ClassNameCheck => { :pattern => /^[A-Z][a-zA-Z0-9]*$/ },
19
- :SingletonVariableCheck => { },
20
- :GlobalVariableCheck => { },
21
- :EmptyRescueBodyCheck => { },
22
- :MethodLineCountCheck => { :line_count => 20 },
23
- :MethodNameCheck => { :pattern => /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ },
24
- :ModuleLineCountCheck => { :line_count => 300 },
25
- :ModuleNameCheck => { :pattern => /^[A-Z][a-zA-Z0-9]*$/ },
26
- :ParameterNumberCheck => { :parameter_count => 3 },
27
- :'Rails::AttrProtectedCheck' => { },
28
- :'Rails::AttrAccessibleCheck' => { },
29
- :'Rails::InstanceVarInPartialCheck' => { },
30
- :'Rails::ValidationsCheck' => { },
31
- :'Rails::ParamsHashInViewCheck' => { },
32
- :'Rails::SessionHashInViewCheck' => { },
33
- :'Rails::CustomInitializeMethodCheck' => { }
14
+ DEFAULT_CHECKS_CONFIG = {
15
+ :AbcMetricMethodCheck => {},
16
+ :AssignmentInConditionalCheck => {},
17
+ :CaseMissingElseCheck => {},
18
+ :ClassLineCountCheck => {},
19
+ :ClassNameCheck => {},
20
+ :ControlCouplingCheck => {},
21
+ :CyclomaticComplexityBlockCheck => {},
22
+ :CyclomaticComplexityMethodCheck => {},
23
+ :EmptyRescueBodyCheck => {},
24
+ :FlogBlockCheck => {},
25
+ :FlogClassCheck => {},
26
+ :FlogMethodCheck => {},
27
+ :ForLoopCheck => {},
28
+ :GlobalVariableCheck => {},
29
+ :MethodLineCountCheck => {},
30
+ :MethodNameCheck => {},
31
+ :ModuleLineCountCheck => {},
32
+ :ModuleNameCheck => {},
33
+ :ParameterNumberCheck => {},
34
+ :ClassVariableCheck => {},
35
+ :'Rails::AttrProtectedCheck' => {},
36
+ :'Rails::AttrAccessibleCheck' => {},
37
+ :'Rails::InstanceVarInPartialCheck' => {},
38
+ :'Rails::ValidationsCheck' => {},
39
+ :'Rails::ParamsHashInViewCheck' => {},
40
+ :'Rails::SessionHashInViewCheck' => {},
41
+ :'Rails::CustomInitializeMethodCheck' => {}
34
42
  }
35
43
 
36
- attr_accessor :config #:nodoc:
44
+ attr_reader :checks
37
45
 
38
46
  # Initializes a Runner
39
47
  #
40
48
  # ==== Parameters
41
49
  #
42
- # * <tt>checks</tt> - The checks to apply - pass instances of the various check classes. If no checks are specified, all checks will be applied.
43
- def initialize(*checks)
44
- @config = DEFAULT_CONFIG
45
- @checks = checks unless checks.empty?
50
+ # * <tt>checks_config</tt> - The check configuration to use; You can either specify an array of specs to use like this
51
+ # [:ClassLineCountCheck => { :threshold => 10 }]
52
+ # or you can specify a hash that will then be merged with the default configuration:
53
+ # { :ClassNameCheck => { pattern: 'test' }, :ClassLineCountCheck => { :threshold => 10 } }
54
+ # You can enable/disable a check by setting the value of the hash to sth. truthy/falsy:
55
+ # { :ClassNameCheck => false, :AbcMetricMethodCheck => {} }
56
+ def initialize(checks_config = {})
57
+ @checks = load_checks(checks_config)
46
58
  @parser = Parsing::Parser.new
47
59
  end
48
60
 
@@ -53,7 +65,6 @@ module Simplabs
53
65
  # * <tt>filename</tt> - The name of the file the code was read from.
54
66
  # * <tt>code</tt> - The code to process (String).
55
67
  def check(filename, code)
56
- @checks ||= load_checks
57
68
  @processor ||= Parsing::CodeProcessor.new(@checks)
58
69
  node = parse(filename, code)
59
70
  @processor.process(node)
@@ -67,7 +78,7 @@ module Simplabs
67
78
  def check_code(code)
68
79
  check('dummy-file.rb', code)
69
80
  end
70
-
81
+
71
82
  # Processes the file +filename+. The code will be read from the file.
72
83
  #
73
84
  # ==== Parameters
@@ -94,7 +105,6 @@ module Simplabs
94
105
 
95
106
  # Gets the warnings that were produced by the checks.
96
107
  def warnings
97
- @checks ||= []
98
108
  @checks.collect { |check| check.warnings }.flatten
99
109
  end
100
110
 
@@ -104,11 +114,18 @@ module Simplabs
104
114
  @parser.parse(code, filename)
105
115
  end
106
116
 
107
- def load_checks
117
+ def load_checks(checks_config)
118
+ effective_checks = checks_config.is_a?(Array) ? checks_config : [DEFAULT_CHECKS_CONFIG.deep_merge(checks_config.deep_symbolize_keys)]
108
119
  check_objects = []
109
- DEFAULT_CONFIG.each_pair do |key, value|
110
- klass = eval("Simplabs::Excellent::Checks::#{key.to_s}")
111
- check_objects << (value.empty? ? klass.new : klass.new(value))
120
+ effective_checks.each do |check|
121
+ check.each do |name, check_config|
122
+ if !!check_config
123
+ klass = name.to_s.split('::').inject(::Simplabs::Excellent::Checks) do |mod, class_name|
124
+ mod.const_get(class_name)
125
+ end
126
+ check_objects << klass.new(check_config.is_a?(Hash) ? check_config.deep_symbolize_keys : {})
127
+ end
128
+ end
112
129
  end
113
130
  check_objects
114
131
  end