reek 3.2.1 → 3.3.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 (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