reek 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/History.txt +44 -4
  2. data/License.txt +20 -0
  3. data/README.rdoc +83 -0
  4. data/Rakefile +0 -1
  5. data/bin/reek +3 -11
  6. data/config/defaults.reek +20 -1
  7. data/features/masking_smells.feature +111 -0
  8. data/features/options.feature +49 -0
  9. data/features/reports.feature +90 -0
  10. data/features/samples.feature +284 -0
  11. data/features/stdin.feature +43 -0
  12. data/features/step_definitions/reek_steps.rb +35 -0
  13. data/features/support/env.rb +38 -0
  14. data/lib/reek.rb +1 -1
  15. data/lib/reek/adapters/application.rb +47 -0
  16. data/lib/reek/adapters/config_file.rb +31 -0
  17. data/lib/reek/adapters/core_extras.rb +72 -0
  18. data/lib/reek/{object_source.rb → adapters/object_source.rb} +15 -19
  19. data/lib/reek/{rake_task.rb → adapters/rake_task.rb} +2 -2
  20. data/lib/reek/adapters/report.rb +91 -0
  21. data/lib/reek/adapters/source.rb +53 -0
  22. data/lib/reek/{spec.rb → adapters/spec.rb} +45 -60
  23. data/lib/reek/block_context.rb +1 -1
  24. data/lib/reek/class_context.rb +26 -6
  25. data/lib/reek/code_context.rb +8 -0
  26. data/lib/reek/code_parser.rb +82 -39
  27. data/lib/reek/command_line.rb +85 -0
  28. data/lib/reek/configuration.rb +51 -0
  29. data/lib/reek/detector_stack.rb +39 -0
  30. data/lib/reek/exceptions.reek +8 -1
  31. data/lib/reek/method_context.rb +53 -11
  32. data/lib/reek/module_context.rb +1 -2
  33. data/lib/reek/name.rb +8 -2
  34. data/lib/reek/sexp_formatter.rb +2 -0
  35. data/lib/reek/smell_warning.rb +26 -8
  36. data/lib/reek/smells/control_couple.rb +8 -4
  37. data/lib/reek/smells/data_clump.rb +88 -0
  38. data/lib/reek/smells/duplication.rb +11 -9
  39. data/lib/reek/smells/feature_envy.rb +3 -4
  40. data/lib/reek/smells/large_class.rb +17 -17
  41. data/lib/reek/smells/long_method.rb +10 -8
  42. data/lib/reek/smells/long_parameter_list.rb +16 -10
  43. data/lib/reek/smells/long_yield_list.rb +1 -1
  44. data/lib/reek/smells/nested_iterators.rb +3 -3
  45. data/lib/reek/smells/simulated_polymorphism.rb +58 -0
  46. data/lib/reek/smells/smell_detector.rb +94 -27
  47. data/lib/reek/smells/uncommunicative_name.rb +23 -23
  48. data/lib/reek/smells/utility_function.rb +27 -11
  49. data/lib/reek/sniffer.rb +183 -0
  50. data/reek.gemspec +5 -5
  51. data/spec/quality/reek_source_spec.rb +15 -0
  52. data/spec/reek/adapters/report_spec.rb +49 -0
  53. data/spec/reek/adapters/should_reek_of_spec.rb +108 -0
  54. data/spec/reek/adapters/should_reek_only_of_spec.rb +87 -0
  55. data/spec/reek/adapters/should_reek_spec.rb +92 -0
  56. data/spec/reek/block_context_spec.rb +7 -1
  57. data/spec/reek/class_context_spec.rb +39 -16
  58. data/spec/reek/code_context_spec.rb +7 -7
  59. data/spec/reek/code_parser_spec.rb +6 -1
  60. data/spec/reek/config_spec.rb +3 -3
  61. data/spec/reek/configuration_spec.rb +12 -0
  62. data/spec/reek/method_context_spec.rb +2 -2
  63. data/spec/reek/name_spec.rb +24 -0
  64. data/spec/reek/object_source_spec.rb +23 -0
  65. data/spec/reek/singleton_method_context_spec.rb +2 -2
  66. data/spec/reek/smell_warning_spec.rb +53 -0
  67. data/spec/reek/smells/data_clump_spec.rb +87 -0
  68. data/spec/reek/smells/duplication_spec.rb +13 -17
  69. data/spec/reek/smells/feature_envy_spec.rb +23 -28
  70. data/spec/reek/smells/large_class_spec.rb +109 -34
  71. data/spec/reek/smells/long_method_spec.rb +140 -3
  72. data/spec/reek/smells/long_parameter_list_spec.rb +1 -2
  73. data/spec/reek/smells/simulated_polymorphism_spec.rb +50 -0
  74. data/spec/reek/smells/smell_detector_spec.rb +53 -0
  75. data/spec/reek/smells/uncommunicative_name_spec.rb +20 -7
  76. data/spec/reek/smells/utility_function_spec.rb +76 -67
  77. data/spec/reek/sniffer_spec.rb +10 -0
  78. data/spec/samples/all_but_one_masked/clean_one.rb +6 -0
  79. data/spec/samples/all_but_one_masked/dirty.rb +7 -0
  80. data/spec/samples/all_but_one_masked/masked.reek +5 -0
  81. data/spec/samples/clean_due_to_masking/clean_one.rb +6 -0
  82. data/spec/samples/clean_due_to_masking/clean_three.rb +6 -0
  83. data/spec/samples/clean_due_to_masking/clean_two.rb +6 -0
  84. data/spec/samples/clean_due_to_masking/dirty_one.rb +7 -0
  85. data/spec/samples/clean_due_to_masking/dirty_two.rb +7 -0
  86. data/spec/samples/clean_due_to_masking/masked.reek +7 -0
  87. data/spec/samples/corrupt_config_file/corrupt.reek +1 -0
  88. data/spec/samples/corrupt_config_file/dirty.rb +7 -0
  89. data/spec/samples/empty_config_file/dirty.rb +7 -0
  90. data/spec/samples/empty_config_file/empty.reek +0 -0
  91. data/spec/samples/exceptions.reek +4 -0
  92. data/spec/{slow/samples → samples}/inline.rb +0 -0
  93. data/spec/samples/masked/dirty.rb +7 -0
  94. data/spec/samples/masked/masked.reek +3 -0
  95. data/spec/samples/mixed_results/clean_one.rb +6 -0
  96. data/spec/samples/mixed_results/clean_three.rb +6 -0
  97. data/spec/samples/mixed_results/clean_two.rb +6 -0
  98. data/spec/samples/mixed_results/dirty_one.rb +7 -0
  99. data/spec/samples/mixed_results/dirty_two.rb +7 -0
  100. data/spec/samples/not_quite_masked/dirty.rb +8 -0
  101. data/spec/samples/not_quite_masked/masked.reek +5 -0
  102. data/spec/{slow/samples → samples}/optparse.rb +0 -0
  103. data/spec/samples/overrides/masked/dirty.rb +7 -0
  104. data/spec/samples/overrides/masked/lower.reek +5 -0
  105. data/spec/samples/overrides/upper.reek +5 -0
  106. data/spec/{slow/samples → samples}/redcloth.rb +0 -0
  107. data/spec/samples/three_clean_files/clean_one.rb +6 -0
  108. data/spec/samples/three_clean_files/clean_three.rb +6 -0
  109. data/spec/samples/three_clean_files/clean_two.rb +6 -0
  110. data/spec/samples/two_smelly_files/dirty_one.rb +7 -0
  111. data/spec/samples/two_smelly_files/dirty_two.rb +7 -0
  112. data/spec/spec.opts +1 -1
  113. data/spec/spec_helper.rb +4 -4
  114. data/tasks/reek.rake +8 -5
  115. data/tasks/test.rake +51 -0
  116. metadata +75 -25
  117. data/README.txt +0 -6
  118. data/lib/reek/options.rb +0 -92
  119. data/lib/reek/report.rb +0 -81
  120. data/lib/reek/smells/smells.rb +0 -81
  121. data/lib/reek/source.rb +0 -127
  122. data/spec/reek/options_spec.rb +0 -13
  123. data/spec/reek/report_spec.rb +0 -48
  124. data/spec/reek/smells/smell_spec.rb +0 -24
  125. data/spec/slow/inline_spec.rb +0 -43
  126. data/spec/slow/optparse_spec.rb +0 -108
  127. data/spec/slow/redcloth_spec.rb +0 -101
  128. data/spec/slow/reek_source_spec.rb +0 -20
  129. data/spec/slow/script_spec.rb +0 -55
  130. data/spec/slow/source_list_spec.rb +0 -40
  131. data/tasks/rspec.rake +0 -21
@@ -0,0 +1,39 @@
1
+
2
+ module Reek
3
+ class DetectorStack
4
+
5
+ def initialize(default_detector)
6
+ @detectors = [default_detector]
7
+ end
8
+
9
+ def push(config)
10
+ clone = @detectors[-1].supersede_with(config)
11
+ @detectors << clone
12
+ end
13
+
14
+ def listen_to(hooks)
15
+ @detectors.each { |det| det.listen_to(hooks) }
16
+ end
17
+
18
+ def report_on(report)
19
+ @detectors.each { |det| det.report_on(report) }
20
+ end
21
+
22
+ def num_smells
23
+ total = 0
24
+ @detectors.each { |det| total += det.num_smells }
25
+ total
26
+ end
27
+
28
+ def has_smell?(patterns)
29
+ @detectors.each { |det| return true if det.has_smell?(patterns) }
30
+ false
31
+ end
32
+
33
+ def smelly?
34
+ # SMELL: Duplication: look at al those loops!
35
+ @detectors.each { |det| return true if det.smelly? }
36
+ false
37
+ end
38
+ end
39
+ end
@@ -1,4 +1,7 @@
1
- ---
1
+ ---
2
+ Duplication:
3
+ exclude:
4
+ - Reek::Options#set_options
2
5
  FeatureEnvy:
3
6
  exclude:
4
7
  - examine_context
@@ -8,6 +11,10 @@ LargeClass:
8
11
  LongMethod:
9
12
  exclude:
10
13
  - Reek::SexpFormatter#self.format
14
+ - Reek::Options#set_options
15
+ UncommunicativeName:
16
+ accept:
17
+ - process_op_asgn1
11
18
  UtilityFunction:
12
19
  exclude:
13
20
  - Reek::Spec
@@ -2,7 +2,55 @@ require 'reek/name'
2
2
  require 'reek/code_context'
3
3
  require 'reek/object_refs'
4
4
 
5
+ class Array
6
+ def power_set
7
+ self.inject([[]]) { |cum, element| cum.cross(element) }
8
+ end
9
+
10
+ def bounded_power_set(lower_bound)
11
+ power_set.select {|ps| ps.length > lower_bound}
12
+ end
13
+
14
+ def cross(element)
15
+ result = []
16
+ self.each do |set|
17
+ result << set
18
+ result << (set + [element])
19
+ end
20
+ result
21
+ end
22
+
23
+ def intersection
24
+ self.inject { |res, elem| elem & res }
25
+ end
26
+ end
27
+
5
28
  module Reek
29
+
30
+ module MethodParameters
31
+ def self.is_arg?(param)
32
+ return false if (Array === param and param[0] == :block)
33
+ return !(param.to_s =~ /^\&/)
34
+ end
35
+
36
+ def names
37
+ return @names if @names
38
+ @names = self[1..-1].select {|arg| MethodParameters.is_arg?(arg)}.map {|arg| Name.new(arg)}
39
+ end
40
+
41
+ def length
42
+ names.length
43
+ end
44
+
45
+ def include?(name)
46
+ names.include?(name)
47
+ end
48
+
49
+ def to_s
50
+ "[#{names.map{|nm| nm.to_s}.join(', ')}]"
51
+ end
52
+ end
53
+
6
54
  class MethodContext < CodeContext
7
55
  attr_reader :parameters
8
56
  attr_reader :calls
@@ -11,14 +59,16 @@ module Reek
11
59
 
12
60
  def initialize(outer, exp, record = true)
13
61
  super(outer, exp)
14
- @parameters = []
62
+ @parameters = exp[exp[0] == :defn ? 2 : 3] # SMELL: SimulatedPolymorphism
63
+ @parameters ||= []
64
+ @parameters.extend(MethodParameters)
15
65
  @local_variables = []
16
66
  @name = Name.new(exp[1])
17
67
  @num_statements = 0
18
68
  @calls = Hash.new(0)
19
69
  @depends_on_self = false
20
70
  @refs = ObjectRefs.new
21
- @outer.record_method(@name) # TODO: should be children of outer?
71
+ @outer.record_method(self)
22
72
  end
23
73
 
24
74
  def count_statements(num)
@@ -63,14 +113,6 @@ module Reek
63
113
  @local_variables << Name.new(sym)
64
114
  end
65
115
 
66
- def self.is_block_arg?(param)
67
- (Array === param and param[0] == :block) or (param.to_s =~ /^\&/)
68
- end
69
-
70
- def record_parameter(param)
71
- @parameters << Name.new(param) unless MethodContext.is_block_arg?(param)
72
- end
73
-
74
116
  def outer_name
75
117
  "#{@outer.outer_name}#{@name}/"
76
118
  end
@@ -85,7 +127,7 @@ module Reek
85
127
  end
86
128
 
87
129
  def variable_names
88
- @parameters + @local_variables
130
+ @parameters.names + @local_variables
89
131
  end
90
132
  end
91
133
  end
@@ -19,8 +19,7 @@ module Reek
19
19
 
20
20
  def find_module(modname)
21
21
  return nil unless myself
22
- sym = modname.to_s
23
- @myself.const_defined?(sym) ? @myself.const_get(sym) : nil
22
+ @myself.const_or_nil(modname.to_s)
24
23
  end
25
24
 
26
25
  def outer_name
data/lib/reek/name.rb CHANGED
@@ -32,16 +32,22 @@ module Reek
32
32
  @name.hash
33
33
  end
34
34
 
35
+ def eql?(other)
36
+ self == other
37
+ end
38
+
35
39
  def <=>(other) # :nodoc:
36
40
  @name <=> other.to_s
37
41
  end
38
42
 
39
- alias eql? <=>
40
-
41
43
  def effective_name
42
44
  @name.gsub(/^@*/, '')
43
45
  end
44
46
 
47
+ def inspect
48
+ @name.inspect
49
+ end
50
+
45
51
  def to_s
46
52
  @name
47
53
  end
@@ -1,3 +1,5 @@
1
+ require 'rubygems'
2
+ require 'ruby_parser'
1
3
  require 'ruby2ruby'
2
4
 
3
5
  module Reek
@@ -1,4 +1,4 @@
1
- require 'reek/options'
1
+ require 'reek/command_line' # SMELL: Global Variable used for options
2
2
 
3
3
  module Reek
4
4
 
@@ -8,18 +8,19 @@ module Reek
8
8
  class SmellWarning
9
9
  include Comparable
10
10
 
11
- def initialize(smell, context, warning)
12
- @smell = smell
11
+ def initialize(smell, context, warning, masked)
12
+ @detector = smell
13
13
  @context = context
14
14
  @warning = warning
15
+ @is_masked = masked
15
16
  end
16
17
 
17
18
  def hash # :nodoc:
18
- report.hash
19
+ basic_report.hash
19
20
  end
20
21
 
21
22
  def <=>(other)
22
- report <=> other.report
23
+ basic_report <=> other.basic_report
23
24
  end
24
25
 
25
26
  alias eql? <=> # :nodoc:
@@ -29,21 +30,38 @@ module Reek
29
30
  # +smell_class+ and its report string matches all of the +patterns+.
30
31
  #
31
32
  def matches?(smell_class, patterns)
32
- return false unless smell_class.to_s == @smell.class.class_name
33
+ return false unless smell_class.to_s == @detector.class.class_name
34
+ contains_all?(patterns)
35
+ end
36
+
37
+ def contains_all?(patterns)
33
38
  rpt = report
34
39
  return patterns.all? {|exp| exp === rpt}
35
40
  end
36
41
 
42
+ def basic_report
43
+ Options[:format].gsub(/\%s/, @detector.smell_name).gsub(/\%c/, @context.to_s).gsub(/\%w/, @warning)
44
+ end
45
+
37
46
  #
38
47
  # Returns a copy of the current report format (see +Options+)
39
48
  # in which the following magic tokens have been substituted:
40
49
  #
41
- # * %s <-- the name of the smell that was detected
42
50
  # * %c <-- a description of the +CodeContext+ containing the smell
51
+ # * %m <-- "(is_masked) " if this is a is_masked smell
52
+ # * %s <-- the name of the smell that was detected
43
53
  # * %w <-- the specific problem that was detected
44
54
  #
45
55
  def report
46
- Options[:format].gsub(/\%s/, @smell.smell_name).gsub(/\%c/, @context.to_s).gsub(/\%w/, @warning)
56
+ basic_report.gsub(/\%m/, @is_masked ? '(masked) ' : '')
57
+ end
58
+
59
+ def report_on(report)
60
+ if @is_masked
61
+ report.record_masked_smell(self)
62
+ else
63
+ report << self
64
+ end
47
65
  end
48
66
  end
49
67
  end
@@ -49,12 +49,16 @@ module Reek
49
49
 
50
50
  #
51
51
  # Checks whether the given conditional statement relies on a control couple.
52
- # Any smells found are added to the +report+.
52
+ # Remembers any smells found.
53
53
  #
54
- def examine_context(cond, report)
54
+ def examine_context(cond)
55
55
  return unless cond.tests_a_parameter?
56
- report << SmellWarning.new(self, cond,
57
- "is controlled by argument #{SexpFormatter.format(cond.if_expr)}")
56
+ # SMELL: Duplication
57
+ # This smell is reported once for each conditional that tests the
58
+ # same parameter. Which means that the same smell can recur within
59
+ # a single sniffer. Which in turn means that the sniffer can't count
60
+ # its smells without knowing which are duplicates.
61
+ found(cond, "is controlled by argument #{SexpFormatter.format(cond.if_expr)}")
58
62
  end
59
63
  end
60
64
  end
@@ -0,0 +1,88 @@
1
+ require 'reek/smells/smell_detector'
2
+ require 'reek/smell_warning'
3
+ require 'reek/sexp_formatter'
4
+
5
+ module Reek
6
+ module Smells
7
+
8
+ #
9
+ # A Data Clump occurs when the same two or three items frequently
10
+ # appear together in classes and parameter lists, or when a group
11
+ # of instance variable names start or end with similar substrings.
12
+ #
13
+ # The recurrence of the items often means there is duplicate code
14
+ # spread around to handle them. There may be an abstraction missing
15
+ # from the code, making the system harder to understand.
16
+ #
17
+ # Currently Reek looks for a group of two or more parameters with
18
+ # the same names that are expected by three or more methods of a class.
19
+ #
20
+ class DataClump < SmellDetector
21
+
22
+ def self.contexts # :nodoc:
23
+ [:class]
24
+ end
25
+
26
+ # The name of the config field that sets the maximum allowed
27
+ # copies of any clump.
28
+ MAX_COPIES_KEY = 'max_copies'
29
+
30
+ DEFAULT_MAX_COPIES = 2
31
+
32
+ MIN_CLUMP_SIZE_KEY = 'min_clump_size'
33
+ DEFAULT_MIN_CLUMP_SIZE = 2
34
+
35
+ def self.default_config
36
+ super.adopt(
37
+ MAX_COPIES_KEY => DEFAULT_MAX_COPIES,
38
+ MIN_CLUMP_SIZE_KEY => DEFAULT_MIN_CLUMP_SIZE
39
+ )
40
+ end
41
+
42
+ def initialize(config = DataClump.default_config)
43
+ super(config)
44
+ end
45
+
46
+ #
47
+ # Checks the given ClassContext for multiple identical conditional tests.
48
+ # Remembers any smells found.
49
+ #
50
+ def examine_context(klass)
51
+ max_copies = value(MAX_COPIES_KEY, klass, DEFAULT_MAX_COPIES)
52
+ min_clump_size = value(MIN_CLUMP_SIZE_KEY, klass, DEFAULT_MIN_CLUMP_SIZE)
53
+ MethodGroup.new(klass, min_clump_size, max_copies).clumps.each do |clump, occurs|
54
+ found(klass, "takes parameters #{DataClump.print_clump(clump)} to #{occurs} methods")
55
+ end
56
+ end
57
+
58
+ def self.print_clump(clump)
59
+ "[#{clump.map {|name| name.to_s}.join(', ')}]"
60
+ end
61
+ end
62
+ end
63
+
64
+ # Represents a group of methods
65
+ class MethodGroup # :nodoc:
66
+
67
+ def self.intersection_of_parameters_of(methods)
68
+ methods.map {|meth| meth.parameters.names.sort}.intersection
69
+ end
70
+
71
+ def initialize(klass, min_clump_size, max_copies)
72
+ @klass = klass
73
+ @min_clump_size = min_clump_size
74
+ @max_copies = max_copies
75
+ end
76
+
77
+ def clumps
78
+ results = Hash.new(0)
79
+ @klass.parameterized_methods(@min_clump_size).bounded_power_set(@max_copies).each do |methods|
80
+ clump = MethodGroup.intersection_of_parameters_of(methods)
81
+ if clump.length >= @min_clump_size
82
+ results[clump] = [methods.length, results[clump]].max
83
+ end
84
+ end
85
+ results
86
+ end
87
+ end
88
+ end
@@ -24,26 +24,28 @@ module Reek
24
24
  # identical calls to be permitted within any single method.
25
25
  MAX_ALLOWED_CALLS_KEY = 'max_calls'
26
26
 
27
+ DEFAULT_MAX_CALLS = 1
28
+
27
29
  def self.default_config
28
- super.adopt(MAX_ALLOWED_CALLS_KEY => 1)
30
+ super.adopt(MAX_ALLOWED_CALLS_KEY => DEFAULT_MAX_CALLS)
29
31
  end
30
32
 
31
33
  def initialize(config = Duplication.default_config)
32
- super
33
- @max_calls = config[MAX_ALLOWED_CALLS_KEY]
34
+ super(config)
34
35
  end
35
36
 
36
- def examine_context(method, report)
37
- smelly_calls(method).each do |call|
38
- report << SmellWarning.new(self, method,
39
- "calls #{SexpFormatter.format(call)} multiple times")
37
+ def examine_context(method)
38
+ smelly_calls(method).each do |call_data|
39
+ num = call_data[1]
40
+ multiple = num == 2 ? 'twice' : "#{num} times"
41
+ found(method, "calls #{SexpFormatter.format(call_data[0])} #{multiple}")
40
42
  end
41
43
  end
42
44
 
43
45
  def smelly_calls(method) # :nodoc:
44
46
  method.calls.select do |key,val|
45
- val > @max_calls and key[2] != :new
46
- end.map { |call_exp| call_exp[0] }
47
+ val > value(MAX_ALLOWED_CALLS_KEY, method, DEFAULT_MAX_CALLS) and key[2] != :new
48
+ end
47
49
  end
48
50
  end
49
51
  end
@@ -45,12 +45,11 @@ module Reek
45
45
  #
46
46
  # Checks whether the given +context+ includes any code fragment that
47
47
  # might "belong" on another class.
48
- # Any smells found are added to the +report+.
48
+ # Remembers any smells found.
49
49
  #
50
- def examine_context(context, report)
50
+ def examine_context(context)
51
51
  context.envious_receivers.each do |ref|
52
- report << SmellWarning.new(self, context,
53
- "refers to #{SexpFormatter.format(ref)} more than self")
52
+ found(context, "refers to #{SexpFormatter.format(ref)} more than self")
54
53
  end
55
54
  end
56
55
  end
@@ -20,49 +20,49 @@ module Reek
20
20
  # permitted in a class.
21
21
  MAX_ALLOWED_METHODS_KEY = 'max_methods'
22
22
 
23
+ DEFAULT_MAX_METHODS = 25
24
+
23
25
  # The name of the config field that sets the maximum number of instance
24
26
  # variables permitted in a class.
25
27
  MAX_ALLOWED_IVARS_KEY = 'max_instance_variables'
26
28
 
29
+ DEFAULT_MAX_IVARS = 9
30
+
27
31
  def self.contexts # :nodoc:
28
32
  [:class]
29
33
  end
30
34
 
31
35
  def self.default_config
32
36
  super.adopt(
33
- MAX_ALLOWED_METHODS_KEY => 25,
34
- MAX_ALLOWED_IVARS_KEY => 9,
37
+ MAX_ALLOWED_METHODS_KEY => DEFAULT_MAX_METHODS,
38
+ MAX_ALLOWED_IVARS_KEY => DEFAULT_MAX_IVARS,
35
39
  EXCLUDE_KEY => []
36
40
  )
37
41
  end
38
42
 
39
43
  def initialize(config = LargeClass.default_config)
40
- super
41
- @max_methods = config[MAX_ALLOWED_METHODS_KEY]
42
- @max_instance_variables = config[MAX_ALLOWED_IVARS_KEY]
44
+ super(config)
43
45
  end
44
46
 
45
- def check_num_methods(klass, report) # :nodoc:
47
+ def check_num_methods(klass) # :nodoc:
46
48
  count = klass.num_methods
47
- return if count <= @max_methods
48
- report << SmellWarning.new(self, klass,
49
- "has at least #{count} methods")
49
+ return if count <= value(MAX_ALLOWED_METHODS_KEY, klass, DEFAULT_MAX_METHODS)
50
+ found(klass, "has at least #{count} methods")
50
51
  end
51
52
 
52
- def check_num_ivars(klass, report) # :nodoc:
53
+ def check_num_ivars(klass) # :nodoc:
53
54
  count = klass.variable_names.length
54
- return if count <= @max_instance_variables
55
- report << SmellWarning.new(self, klass,
56
- "has at least #{count} instance variables")
55
+ return if count <= value(MAX_ALLOWED_IVARS_KEY, klass, DEFAULT_MAX_IVARS)
56
+ found(klass, "has at least #{count} instance variables")
57
57
  end
58
58
 
59
59
  #
60
60
  # Checks +klass+ for too many methods or too many instance variables.
61
- # Any smells found are added to the +report+.
61
+ # Remembers any smells found.
62
62
  #
63
- def examine_context(klass, report)
64
- check_num_methods(klass, report)
65
- check_num_ivars(klass, report)
63
+ def examine_context(klass)
64
+ check_num_methods(klass)
65
+ check_num_ivars(klass)
66
66
  end
67
67
  end
68
68
  end