reek 3.2.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/Rakefile +0 -1
  4. data/config/defaults.reek +1 -1
  5. data/features/samples.feature +17 -16
  6. data/lib/reek.rb +0 -1
  7. data/lib/reek/ast/ast_node_class_map.rb +5 -1
  8. data/lib/reek/ast/node.rb +10 -3
  9. data/lib/reek/ast/object_refs.rb +11 -5
  10. data/lib/reek/ast/reference_collector.rb +6 -2
  11. data/lib/reek/ast/sexp_extensions.rb +42 -1
  12. data/lib/reek/ast/sexp_formatter.rb +2 -1
  13. data/lib/reek/cli/application.rb +12 -9
  14. data/lib/reek/cli/command.rb +6 -0
  15. data/lib/reek/cli/input.rb +4 -4
  16. data/lib/reek/cli/option_interpreter.rb +11 -7
  17. data/lib/reek/cli/options.rb +42 -40
  18. data/lib/reek/cli/reek_command.rb +3 -3
  19. data/lib/reek/cli/silencer.rb +12 -3
  20. data/lib/reek/cli/warning_collector.rb +8 -3
  21. data/lib/reek/code_comment.rb +6 -1
  22. data/lib/reek/configuration/app_configuration.rb +65 -100
  23. data/lib/reek/configuration/configuration_file_finder.rb +4 -13
  24. data/lib/reek/configuration/configuration_validator.rb +35 -0
  25. data/lib/reek/configuration/default_directive.rb +12 -0
  26. data/lib/reek/configuration/directory_directives.rb +54 -0
  27. data/lib/reek/configuration/excluded_paths.rb +18 -0
  28. data/lib/reek/context/code_context.rb +19 -17
  29. data/lib/reek/examiner.rb +9 -7
  30. data/lib/reek/rake/task.rb +12 -22
  31. data/lib/reek/report/formatter.rb +6 -1
  32. data/lib/reek/report/report.rb +22 -13
  33. data/lib/reek/smells/attribute.rb +6 -53
  34. data/lib/reek/smells/control_parameter.rb +21 -13
  35. data/lib/reek/smells/data_clump.rb +17 -9
  36. data/lib/reek/smells/duplicate_method_call.rb +12 -6
  37. data/lib/reek/smells/long_parameter_list.rb +2 -2
  38. data/lib/reek/smells/long_yield_list.rb +4 -4
  39. data/lib/reek/smells/nested_iterators.rb +4 -2
  40. data/lib/reek/smells/nil_check.rb +6 -2
  41. data/lib/reek/smells/repeated_conditional.rb +3 -3
  42. data/lib/reek/smells/smell_configuration.rb +17 -7
  43. data/lib/reek/smells/smell_detector.rb +24 -11
  44. data/lib/reek/smells/smell_repository.rb +1 -1
  45. data/lib/reek/smells/smell_warning.rb +6 -6
  46. data/lib/reek/smells/too_many_instance_variables.rb +2 -2
  47. data/lib/reek/smells/too_many_methods.rb +4 -4
  48. data/lib/reek/smells/too_many_statements.rb +4 -4
  49. data/lib/reek/smells/uncommunicative_method_name.rb +5 -5
  50. data/lib/reek/smells/uncommunicative_module_name.rb +6 -6
  51. data/lib/reek/smells/uncommunicative_parameter_name.rb +8 -4
  52. data/lib/reek/smells/uncommunicative_variable_name.rb +9 -5
  53. data/lib/reek/smells/utility_function.rb +1 -1
  54. data/lib/reek/source/source_code.rb +5 -1
  55. data/lib/reek/source/source_locator.rb +3 -2
  56. data/lib/reek/spec.rb +3 -3
  57. data/lib/reek/spec/should_reek.rb +10 -5
  58. data/lib/reek/spec/should_reek_of.rb +9 -6
  59. data/lib/reek/spec/should_reek_only_of.rb +13 -8
  60. data/lib/reek/tree_dresser.rb +6 -2
  61. data/lib/reek/tree_walker.rb +40 -32
  62. data/lib/reek/version.rb +1 -1
  63. data/reek.gemspec +1 -1
  64. data/spec/reek/ast/node_spec.rb +1 -2
  65. data/spec/reek/ast/object_refs_spec.rb +40 -42
  66. data/spec/reek/ast/sexp_extensions_spec.rb +98 -104
  67. data/spec/reek/cli/warning_collector_spec.rb +8 -12
  68. data/spec/reek/code_comment_spec.rb +3 -5
  69. data/spec/reek/configuration/app_configuration_spec.rb +43 -57
  70. data/spec/reek/configuration/configuration_file_finder_spec.rb +5 -7
  71. data/spec/reek/configuration/default_directive_spec.rb +13 -0
  72. data/spec/reek/configuration/directory_directives_spec.rb +89 -0
  73. data/spec/reek/configuration/excluded_paths_spec.rb +30 -0
  74. data/spec/reek/context/code_context_spec.rb +63 -62
  75. data/spec/reek/context/method_context_spec.rb +8 -12
  76. data/spec/reek/context/module_context_spec.rb +1 -1
  77. data/spec/reek/context/root_context_spec.rb +3 -7
  78. data/spec/reek/examiner_spec.rb +14 -25
  79. data/spec/reek/smells/attribute_spec.rb +2 -4
  80. data/spec/reek/smells/boolean_parameter_spec.rb +5 -7
  81. data/spec/reek/smells/class_variable_spec.rb +29 -44
  82. data/spec/reek/smells/control_parameter_spec.rb +7 -9
  83. data/spec/reek/smells/data_clump_spec.rb +25 -32
  84. data/spec/reek/smells/duplicate_method_call_spec.rb +8 -7
  85. data/spec/reek/smells/feature_envy_spec.rb +16 -17
  86. data/spec/reek/smells/irresponsible_module_spec.rb +2 -4
  87. data/spec/reek/smells/long_parameter_list_spec.rb +6 -9
  88. data/spec/reek/smells/long_yield_list_spec.rb +6 -9
  89. data/spec/reek/smells/nested_iterators_spec.rb +14 -16
  90. data/spec/reek/smells/repeated_conditional_spec.rb +25 -25
  91. data/spec/reek/smells/smell_configuration_spec.rb +32 -27
  92. data/spec/reek/smells/smell_detector_shared.rb +12 -13
  93. data/spec/reek/smells/smell_warning_spec.rb +54 -58
  94. data/spec/reek/smells/too_many_instance_variables_spec.rb +9 -9
  95. data/spec/reek/smells/too_many_methods_spec.rb +13 -14
  96. data/spec/reek/smells/too_many_statements_spec.rb +8 -10
  97. data/spec/reek/smells/uncommunicative_method_name_spec.rb +8 -9
  98. data/spec/reek/smells/uncommunicative_module_name_spec.rb +12 -13
  99. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +7 -10
  100. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +16 -20
  101. data/spec/reek/smells/utility_function_spec.rb +11 -15
  102. data/spec/reek/source/source_code_spec.rb +6 -11
  103. data/spec/reek/spec/should_reek_of_spec.rb +19 -30
  104. data/spec/reek/spec/should_reek_only_of_spec.rb +28 -34
  105. data/spec/reek/tree_walker_spec.rb +14 -2
  106. data/spec/spec_helper.rb +2 -3
  107. data/tasks/test.rake +0 -5
  108. metadata +10 -6
  109. data/docs/Configuration-Files.md +0 -49
  110. data/spec/gem/updates_spec.rb +0 -25
  111. data/spec/gem/yard_spec.rb +0 -11
  112. data/spec/reek/smells/behaves_like_variable_detector.rb +0 -39
@@ -38,12 +38,17 @@ module Reek
38
38
  end
39
39
 
40
40
  def inherited(subclass)
41
- @subclasses ||= []
42
- @subclasses << subclass
41
+ subclasses << subclass
43
42
  end
44
43
 
45
44
  def descendants
46
- @subclasses
45
+ subclasses
46
+ end
47
+
48
+ private
49
+
50
+ def subclasses
51
+ @subclasses ||= []
47
52
  end
48
53
  end
49
54
 
@@ -69,7 +74,7 @@ module Reek
69
74
  end
70
75
  end
71
76
 
72
- attr_reader :smells_found # SMELL: only published for tests
77
+ attr_reader :smells_found # SMELL: only published for tests
73
78
 
74
79
  def initialize(source, config = self.class.default_config)
75
80
  @source = source
@@ -78,17 +83,17 @@ module Reek
78
83
  end
79
84
 
80
85
  def register(hooks)
81
- return unless @config.enabled?
86
+ return unless config.enabled?
82
87
  self.class.contexts.each { |ctx| hooks[ctx] << self }
83
88
  end
84
89
 
85
90
  # SMELL: Getter (only used in 1 test)
86
91
  def enabled?
87
- @config.enabled?
92
+ config.enabled?
88
93
  end
89
94
 
90
- def configure_with(config)
91
- @config.merge!(config)
95
+ def configure_with(new_config)
96
+ config.merge!(new_config)
92
97
  end
93
98
 
94
99
  def examine(context)
@@ -96,7 +101,7 @@ module Reek
96
101
  return if exception?(context)
97
102
 
98
103
  sm = examine_context(context)
99
- @smells_found += sm
104
+ self.smells_found += sm
100
105
  end
101
106
 
102
107
  def enabled_for?(context)
@@ -108,16 +113,24 @@ module Reek
108
113
  end
109
114
 
110
115
  def report_on(report)
111
- @smells_found.each { |smell| smell.report_on(report) }
116
+ smells_found.each { |smell| smell.report_on(report) }
112
117
  end
113
118
 
114
119
  def value(key, ctx, fall_back)
115
- config_for(ctx)[key] || @config.value(key, ctx, fall_back)
120
+ config_for(ctx)[key] || config.value(key, ctx, fall_back)
116
121
  end
117
122
 
118
123
  def config_for(ctx)
119
124
  ctx.config_for(self.class)
120
125
  end
126
+
127
+ protected
128
+
129
+ attr_writer :smells_found
130
+
131
+ private
132
+
133
+ private_attr_reader :config
121
134
  end
122
135
  end
123
136
  end
@@ -15,7 +15,7 @@ module Reek
15
15
 
16
16
  def initialize(source_description: nil,
17
17
  smell_types: self.class.smell_types,
18
- configuration: Configuration::AppConfiguration.new)
18
+ configuration: Configuration::AppConfiguration.default)
19
19
  @source_via = source_description
20
20
  @configuration = configuration
21
21
  @smell_types = smell_types
@@ -8,15 +8,15 @@ module Reek
8
8
  class SmellWarning
9
9
  include Comparable
10
10
  extend Forwardable
11
- attr_accessor :smell_detector, :context, :lines, :message, :parameters
11
+ attr_reader :context, :lines, :message, :parameters, :smell_detector
12
12
  def_delegators :smell_detector, :smell_category, :smell_type, :source
13
13
 
14
14
  def initialize(smell_detector, options = {})
15
- self.smell_detector = smell_detector
16
- self.context = options.fetch(:context, '').to_s
17
- self.lines = options.fetch(:lines)
18
- self.message = options.fetch(:message)
19
- self.parameters = options.fetch(:parameters, {})
15
+ @smell_detector = smell_detector
16
+ @context = options.fetch(:context, '').to_s
17
+ @lines = options.fetch(:lines)
18
+ @message = options.fetch(:message)
19
+ @parameters = options.fetch(:parameters, {})
20
20
  end
21
21
 
22
22
  def hash
@@ -39,9 +39,9 @@ module Reek
39
39
  # @return [Array<SmellWarning>]
40
40
  #
41
41
  def examine_context(ctx)
42
- @max_allowed_ivars = value(MAX_ALLOWED_IVARS_KEY, ctx, DEFAULT_MAX_IVARS)
42
+ max_allowed_ivars = value(MAX_ALLOWED_IVARS_KEY, ctx, DEFAULT_MAX_IVARS)
43
43
  count = ctx.local_nodes(:ivasgn).map { |ivasgn| ivasgn[1] }.uniq.length
44
- return [] if count <= @max_allowed_ivars
44
+ return [] if count <= max_allowed_ivars
45
45
  [SmellWarning.new(self,
46
46
  context: ctx.full_name,
47
47
  lines: [ctx.exp.line],
@@ -18,7 +18,7 @@ module Reek
18
18
  # The name of the config field that sets the maximum number of methods
19
19
  # permitted in a class.
20
20
  MAX_ALLOWED_METHODS_KEY = 'max_methods'
21
- DEFAULT_MAX_METHODS = 25
21
+ DEFAULT_MAX_METHODS = 15
22
22
 
23
23
  def self.smell_category
24
24
  'LargeClass'
@@ -41,13 +41,13 @@ module Reek
41
41
  # @return [Array<SmellWarning>]
42
42
  #
43
43
  def examine_context(ctx)
44
- @max_allowed_methods = value(MAX_ALLOWED_METHODS_KEY, ctx, DEFAULT_MAX_METHODS)
44
+ max_allowed_methods = value(MAX_ALLOWED_METHODS_KEY, ctx, DEFAULT_MAX_METHODS)
45
45
  actual = ctx.node_instance_methods.length
46
- return [] if actual <= @max_allowed_methods
46
+ return [] if actual <= max_allowed_methods
47
47
  [SmellWarning.new(self,
48
48
  context: ctx.full_name,
49
49
  lines: [ctx.exp.line],
50
- message: "has at least #{actual} methods",
50
+ message: "has at least #{actual} methods",
51
51
  parameters: { count: actual })]
52
52
  end
53
53
  end
@@ -33,11 +33,11 @@ module Reek
33
33
  # @return [Array<SmellWarning>]
34
34
  #
35
35
  def examine_context(ctx)
36
- @max_allowed_statements = value(MAX_ALLOWED_STATEMENTS_KEY,
37
- ctx,
38
- DEFAULT_MAX_STATEMENTS)
36
+ max_allowed_statements = value(MAX_ALLOWED_STATEMENTS_KEY,
37
+ ctx,
38
+ DEFAULT_MAX_STATEMENTS)
39
39
  count = ctx.num_statements
40
- return [] if count <= @max_allowed_statements
40
+ return [] if count <= max_allowed_statements
41
41
  [SmellWarning.new(self,
42
42
  context: ctx.full_name,
43
43
  lines: [ctx.exp.line],
@@ -47,13 +47,13 @@ module Reek
47
47
  # @return [Array<SmellWarning>]
48
48
  #
49
49
  def examine_context(ctx)
50
- @reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
51
- @accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
50
+ reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
51
+ accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
52
52
  name = ctx.name.to_s
53
- return [] if @accept_names.include?(ctx.full_name)
53
+ return [] if accept_names.include?(ctx.full_name)
54
54
  var = name.gsub(/^[@\*\&]*/, '')
55
- return [] if @accept_names.include?(var)
56
- return [] unless @reject_names.find { |patt| patt =~ var }
55
+ return [] if accept_names.include?(var)
56
+ return [] unless reject_names.find { |patt| patt =~ var }
57
57
  [SmellWarning.new(self,
58
58
  context: ctx.full_name,
59
59
  lines: [ctx.exp.line],
@@ -41,7 +41,7 @@ module Reek
41
41
  )
42
42
  end
43
43
 
44
- def self.contexts # :nodoc:
44
+ def self.contexts # :nodoc:
45
45
  [:module, :class]
46
46
  end
47
47
 
@@ -52,15 +52,15 @@ module Reek
52
52
  #
53
53
  # :reek:Duplication { allow_calls: [ to_s ] }
54
54
  def examine_context(ctx)
55
- @reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
56
- @accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
55
+ reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
56
+ accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
57
57
  exp = ctx.exp
58
58
  full_name = ctx.full_name
59
59
  name = exp.simple_name.to_s
60
- return [] if @accept_names.include?(full_name)
60
+ return [] if accept_names.include?(full_name)
61
61
  var = name.gsub(/^[@\*\&]*/, '')
62
- return [] if @accept_names.include?(var)
63
- return [] unless @reject_names.find { |patt| patt =~ var }
62
+ return [] if accept_names.include?(var)
63
+ return [] unless reject_names.find { |patt| patt =~ var }
64
64
  [SmellWarning.new(self,
65
65
  context: full_name,
66
66
  lines: [exp.line],
@@ -47,8 +47,8 @@ module Reek
47
47
  # @return [Array<SmellWarning>]
48
48
  #
49
49
  def examine_context(ctx)
50
- @reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
51
- @accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
50
+ self.reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
51
+ self.accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
52
52
  context_expression = ctx.exp
53
53
  context_expression.parameter_names.select do |name|
54
54
  bad_name?(name) && ctx.uses_param?(name)
@@ -63,9 +63,13 @@ module Reek
63
63
 
64
64
  def bad_name?(name)
65
65
  var = name.to_s.gsub(/^[@\*\&]*/, '')
66
- return false if var == '*' || @accept_names.include?(var)
67
- @reject_names.find { |patt| patt =~ var }
66
+ return false if var == '*' || accept_names.include?(var)
67
+ reject_names.find { |patt| patt =~ var }
68
68
  end
69
+
70
+ private
71
+
72
+ private_attr_accessor :accept_names, :reject_names
69
73
  end
70
74
  end
71
75
  end
@@ -41,7 +41,7 @@ module Reek
41
41
  )
42
42
  end
43
43
 
44
- def self.contexts # :nodoc:
44
+ def self.contexts # :nodoc:
45
45
  [:module, :class, :def, :defs]
46
46
  end
47
47
 
@@ -51,8 +51,8 @@ module Reek
51
51
  # @return [Array<SmellWarning>]
52
52
  #
53
53
  def examine_context(ctx)
54
- @reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
55
- @accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
54
+ self.reject_names = value(REJECT_KEY, ctx, DEFAULT_REJECT_SET)
55
+ self.accept_names = value(ACCEPT_KEY, ctx, DEFAULT_ACCEPT_SET)
56
56
  variable_names(ctx.exp).select do |name, _lines|
57
57
  bad_name?(name, ctx)
58
58
  end.map do |name, lines|
@@ -66,8 +66,8 @@ module Reek
66
66
 
67
67
  def bad_name?(name, _ctx)
68
68
  var = name.to_s.gsub(/^[@\*\&]*/, '')
69
- return false if @accept_names.include?(var)
70
- @reject_names.find { |patt| patt =~ var }
69
+ return false if accept_names.include?(var)
70
+ reject_names.find { |patt| patt =~ var }
71
71
  end
72
72
 
73
73
  def variable_names(exp)
@@ -121,6 +121,10 @@ module Reek
121
121
  var = varname.to_sym
122
122
  accumulator[var].push(exp.line)
123
123
  end
124
+
125
+ private
126
+
127
+ private_attr_accessor :accept_names, :reject_names
124
128
  end
125
129
  end
126
130
  end
@@ -43,7 +43,7 @@ module Reek
43
43
  end
44
44
 
45
45
  class << self
46
- def contexts # :nodoc:
46
+ def contexts # :nodoc:
47
47
  [:def]
48
48
  end
49
49
  end
@@ -82,7 +82,7 @@ module Reek
82
82
  @syntax_tree ||=
83
83
  begin
84
84
  begin
85
- ast, comments = @parser.parse_with_comments(@source, @description)
85
+ ast, comments = parser.parse_with_comments(source, description)
86
86
  rescue Racc::ParseError, Parser::SyntaxError => error
87
87
  $stderr.puts "#{description}: #{error.class.name}: #{error}"
88
88
  end
@@ -92,6 +92,10 @@ module Reek
92
92
  TreeDresser.new.dress(ast, comment_map)
93
93
  end
94
94
  end
95
+
96
+ private
97
+
98
+ private_attr_reader :parser, :source
95
99
  end
96
100
  end
97
101
  end
@@ -1,3 +1,4 @@
1
+ require 'private_attr/everywhere'
1
2
  require 'find'
2
3
  require 'pathname'
3
4
 
@@ -11,7 +12,7 @@ module Reek
11
12
  # Initialize with the paths we want to search.
12
13
  #
13
14
  # paths - a list of paths as Strings
14
- def initialize(paths, configuration: Configuration::AppConfiguration.new)
15
+ def initialize(paths, configuration: Configuration::AppConfiguration.default)
15
16
  @paths = paths.flat_map do |string|
16
17
  path = Pathname.new(string)
17
18
  current_directory?(path) ? path.entries : path
@@ -45,7 +46,7 @@ module Reek
45
46
  end
46
47
 
47
48
  def path_excluded?(path)
48
- configuration.exclude_paths.include?(path)
49
+ configuration.path_excluded?(path)
49
50
  end
50
51
 
51
52
  def print_no_such_file_error(path)
@@ -87,7 +87,7 @@ module Reek
87
87
  #
88
88
  def reek_of(smell_category,
89
89
  smell_details = {},
90
- configuration = Configuration::AppConfiguration.new)
90
+ configuration = Configuration::AppConfiguration.default)
91
91
  ShouldReekOf.new(smell_category, smell_details, configuration)
92
92
  end
93
93
 
@@ -98,14 +98,14 @@ module Reek
98
98
  # 1.) "reek_of" doesn't mind if there are other smells of a different category.
99
99
  # "reek_only_of" will fail in that case.
100
100
  # 2.) "reek_only_of" doesn't support the additional smell_details hash.
101
- def reek_only_of(smell_category, configuration = Configuration::AppConfiguration.new)
101
+ def reek_only_of(smell_category, configuration = Configuration::AppConfiguration.default)
102
102
  ShouldReekOnlyOf.new(smell_category, configuration)
103
103
  end
104
104
 
105
105
  #
106
106
  # Returns +true+ if and only if the target source code contains smells.
107
107
  #
108
- def reek(configuration = Configuration::AppConfiguration.new)
108
+ def reek(configuration = Configuration::AppConfiguration.default)
109
109
  ShouldReek.new configuration
110
110
  end
111
111
  end
@@ -8,23 +8,28 @@ module Reek
8
8
  #
9
9
  # @api private
10
10
  class ShouldReek
11
- def initialize(configuration = Configuration::AppConfiguration.new)
11
+ def initialize(configuration = Configuration::AppConfiguration.default)
12
12
  @configuration = configuration
13
13
  end
14
14
 
15
15
  def matches?(actual)
16
- @examiner = Examiner.new(actual, configuration: @configuration)
17
- @examiner.smelly?
16
+ self.examiner = Examiner.new(actual, configuration: configuration)
17
+ examiner.smelly?
18
18
  end
19
19
 
20
20
  def failure_message
21
- "Expected #{@examiner.description} to reek, but it didn't"
21
+ "Expected #{examiner.description} to reek, but it didn't"
22
22
  end
23
23
 
24
24
  def failure_message_when_negated
25
- rpt = Report::Formatter.format_list(@examiner.smells)
25
+ rpt = Report::Formatter.format_list(examiner.smells)
26
26
  "Expected no smells, but got:\n#{rpt}"
27
27
  end
28
+
29
+ private
30
+
31
+ private_attr_reader :configuration
32
+ private_attr_accessor :examiner
28
33
  end
29
34
  end
30
35
  end
@@ -10,28 +10,31 @@ module Reek
10
10
  class ShouldReekOf
11
11
  def initialize(smell_category,
12
12
  smell_details = {},
13
- configuration = Configuration::AppConfiguration.new)
13
+ configuration = Configuration::AppConfiguration.default)
14
14
  @smell_category = normalize smell_category
15
15
  @smell_details = smell_details
16
16
  @configuration = configuration
17
17
  end
18
18
 
19
19
  def matches?(actual)
20
- @examiner = Examiner.new(actual, configuration: @configuration)
21
- @all_smells = @examiner.smells
22
- @all_smells.any? { |warning| warning.matches?(@smell_category, @smell_details) }
20
+ self.examiner = Examiner.new(actual, configuration: configuration)
21
+ self.all_smells = examiner.smells
22
+ all_smells.any? { |warning| warning.matches?(smell_category, smell_details) }
23
23
  end
24
24
 
25
25
  def failure_message
26
- "Expected #{@examiner.description} to reek of #{@smell_category}, but it didn't"
26
+ "Expected #{examiner.description} to reek of #{smell_category}, but it didn't"
27
27
  end
28
28
 
29
29
  def failure_message_when_negated
30
- "Expected #{@examiner.description} not to reek of #{@smell_category}, but it did"
30
+ "Expected #{examiner.description} not to reek of #{smell_category}, but it did"
31
31
  end
32
32
 
33
33
  private
34
34
 
35
+ private_attr_reader :configuration, :smell_category, :smell_details
36
+ private_attr_accessor :all_smells, :examiner
37
+
35
38
  def normalize(smell_category_or_type)
36
39
  # In theory, users can give us many different types of input (see the documentation for
37
40
  # reek_of below), however we're basically ignoring all of those subleties and just
@@ -1,5 +1,6 @@
1
1
  require_relative '../examiner'
2
2
  require_relative '../report/formatter'
3
+ require_relative 'should_reek_of'
3
4
 
4
5
  module Reek
5
6
  module Spec
@@ -10,24 +11,28 @@ module Reek
10
11
  # @api private
11
12
  class ShouldReekOnlyOf < ShouldReekOf
12
13
  def matches?(actual)
13
- matches_examiner?(Examiner.new(actual, configuration: @configuration))
14
+ matches_examiner?(Examiner.new(actual, configuration: configuration))
14
15
  end
15
16
 
16
17
  def matches_examiner?(examiner)
17
- @examiner = examiner
18
- @warnings = @examiner.smells
19
- return false if @warnings.empty?
20
- @warnings.all? { |warning| warning.matches?(@smell_category) }
18
+ self.examiner = examiner
19
+ self.warnings = examiner.smells
20
+ return false if warnings.empty?
21
+ warnings.all? { |warning| warning.matches?(smell_category) }
21
22
  end
22
23
 
23
24
  def failure_message
24
- rpt = Report::Formatter.format_list(@warnings)
25
- "Expected #{@examiner.description} to reek only of #{@smell_category}, but got:\n#{rpt}"
25
+ rpt = Report::Formatter.format_list(warnings)
26
+ "Expected #{examiner.description} to reek only of #{smell_category}, but got:\n#{rpt}"
26
27
  end
27
28
 
28
29
  def failure_message_when_negated
29
- "Expected #{@examiner.description} not to reek only of #{@smell_category}, but it did"
30
+ "Expected #{examiner.description} not to reek only of #{smell_category}, but it did"
30
31
  end
32
+
33
+ private
34
+
35
+ private_attr_accessor :warnings
31
36
  end
32
37
  end
33
38
  end