excellent 1.7.2 → 2.0.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.
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