reek 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Rakefile +0 -1
- data/config/defaults.reek +1 -1
- data/features/samples.feature +17 -16
- data/lib/reek.rb +0 -1
- data/lib/reek/ast/ast_node_class_map.rb +5 -1
- data/lib/reek/ast/node.rb +10 -3
- data/lib/reek/ast/object_refs.rb +11 -5
- data/lib/reek/ast/reference_collector.rb +6 -2
- data/lib/reek/ast/sexp_extensions.rb +42 -1
- data/lib/reek/ast/sexp_formatter.rb +2 -1
- data/lib/reek/cli/application.rb +12 -9
- data/lib/reek/cli/command.rb +6 -0
- data/lib/reek/cli/input.rb +4 -4
- data/lib/reek/cli/option_interpreter.rb +11 -7
- data/lib/reek/cli/options.rb +42 -40
- data/lib/reek/cli/reek_command.rb +3 -3
- data/lib/reek/cli/silencer.rb +12 -3
- data/lib/reek/cli/warning_collector.rb +8 -3
- data/lib/reek/code_comment.rb +6 -1
- data/lib/reek/configuration/app_configuration.rb +65 -100
- data/lib/reek/configuration/configuration_file_finder.rb +4 -13
- data/lib/reek/configuration/configuration_validator.rb +35 -0
- data/lib/reek/configuration/default_directive.rb +12 -0
- data/lib/reek/configuration/directory_directives.rb +54 -0
- data/lib/reek/configuration/excluded_paths.rb +18 -0
- data/lib/reek/context/code_context.rb +19 -17
- data/lib/reek/examiner.rb +9 -7
- data/lib/reek/rake/task.rb +12 -22
- data/lib/reek/report/formatter.rb +6 -1
- data/lib/reek/report/report.rb +22 -13
- data/lib/reek/smells/attribute.rb +6 -53
- data/lib/reek/smells/control_parameter.rb +21 -13
- data/lib/reek/smells/data_clump.rb +17 -9
- data/lib/reek/smells/duplicate_method_call.rb +12 -6
- data/lib/reek/smells/long_parameter_list.rb +2 -2
- data/lib/reek/smells/long_yield_list.rb +4 -4
- data/lib/reek/smells/nested_iterators.rb +4 -2
- data/lib/reek/smells/nil_check.rb +6 -2
- data/lib/reek/smells/repeated_conditional.rb +3 -3
- data/lib/reek/smells/smell_configuration.rb +17 -7
- data/lib/reek/smells/smell_detector.rb +24 -11
- data/lib/reek/smells/smell_repository.rb +1 -1
- data/lib/reek/smells/smell_warning.rb +6 -6
- data/lib/reek/smells/too_many_instance_variables.rb +2 -2
- data/lib/reek/smells/too_many_methods.rb +4 -4
- data/lib/reek/smells/too_many_statements.rb +4 -4
- data/lib/reek/smells/uncommunicative_method_name.rb +5 -5
- data/lib/reek/smells/uncommunicative_module_name.rb +6 -6
- data/lib/reek/smells/uncommunicative_parameter_name.rb +8 -4
- data/lib/reek/smells/uncommunicative_variable_name.rb +9 -5
- data/lib/reek/smells/utility_function.rb +1 -1
- data/lib/reek/source/source_code.rb +5 -1
- data/lib/reek/source/source_locator.rb +3 -2
- data/lib/reek/spec.rb +3 -3
- data/lib/reek/spec/should_reek.rb +10 -5
- data/lib/reek/spec/should_reek_of.rb +9 -6
- data/lib/reek/spec/should_reek_only_of.rb +13 -8
- data/lib/reek/tree_dresser.rb +6 -2
- data/lib/reek/tree_walker.rb +40 -32
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +1 -1
- data/spec/reek/ast/node_spec.rb +1 -2
- data/spec/reek/ast/object_refs_spec.rb +40 -42
- data/spec/reek/ast/sexp_extensions_spec.rb +98 -104
- data/spec/reek/cli/warning_collector_spec.rb +8 -12
- data/spec/reek/code_comment_spec.rb +3 -5
- data/spec/reek/configuration/app_configuration_spec.rb +43 -57
- data/spec/reek/configuration/configuration_file_finder_spec.rb +5 -7
- data/spec/reek/configuration/default_directive_spec.rb +13 -0
- data/spec/reek/configuration/directory_directives_spec.rb +89 -0
- data/spec/reek/configuration/excluded_paths_spec.rb +30 -0
- data/spec/reek/context/code_context_spec.rb +63 -62
- data/spec/reek/context/method_context_spec.rb +8 -12
- data/spec/reek/context/module_context_spec.rb +1 -1
- data/spec/reek/context/root_context_spec.rb +3 -7
- data/spec/reek/examiner_spec.rb +14 -25
- data/spec/reek/smells/attribute_spec.rb +2 -4
- data/spec/reek/smells/boolean_parameter_spec.rb +5 -7
- data/spec/reek/smells/class_variable_spec.rb +29 -44
- data/spec/reek/smells/control_parameter_spec.rb +7 -9
- data/spec/reek/smells/data_clump_spec.rb +25 -32
- data/spec/reek/smells/duplicate_method_call_spec.rb +8 -7
- data/spec/reek/smells/feature_envy_spec.rb +16 -17
- data/spec/reek/smells/irresponsible_module_spec.rb +2 -4
- data/spec/reek/smells/long_parameter_list_spec.rb +6 -9
- data/spec/reek/smells/long_yield_list_spec.rb +6 -9
- data/spec/reek/smells/nested_iterators_spec.rb +14 -16
- data/spec/reek/smells/repeated_conditional_spec.rb +25 -25
- data/spec/reek/smells/smell_configuration_spec.rb +32 -27
- data/spec/reek/smells/smell_detector_shared.rb +12 -13
- data/spec/reek/smells/smell_warning_spec.rb +54 -58
- data/spec/reek/smells/too_many_instance_variables_spec.rb +9 -9
- data/spec/reek/smells/too_many_methods_spec.rb +13 -14
- data/spec/reek/smells/too_many_statements_spec.rb +8 -10
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +8 -9
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +12 -13
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +7 -10
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +16 -20
- data/spec/reek/smells/utility_function_spec.rb +11 -15
- data/spec/reek/source/source_code_spec.rb +6 -11
- data/spec/reek/spec/should_reek_of_spec.rb +19 -30
- data/spec/reek/spec/should_reek_only_of_spec.rb +28 -34
- data/spec/reek/tree_walker_spec.rb +14 -2
- data/spec/spec_helper.rb +2 -3
- data/tasks/test.rake +0 -5
- metadata +10 -6
- data/docs/Configuration-Files.md +0 -49
- data/spec/gem/updates_spec.rb +0 -25
- data/spec/gem/yard_spec.rb +0 -11
- 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
|
-
|
42
|
-
@subclasses << subclass
|
41
|
+
subclasses << subclass
|
43
42
|
end
|
44
43
|
|
45
44
|
def descendants
|
46
|
-
|
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
|
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
|
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
|
-
|
92
|
+
config.enabled?
|
88
93
|
end
|
89
94
|
|
90
|
-
def configure_with(
|
91
|
-
|
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
|
-
|
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
|
-
|
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] ||
|
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.
|
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
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
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 <=
|
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 =
|
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
|
-
|
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 <=
|
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:
|
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
|
-
|
37
|
-
|
38
|
-
|
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 <=
|
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
|
-
|
51
|
-
|
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
|
53
|
+
return [] if accept_names.include?(ctx.full_name)
|
54
54
|
var = name.gsub(/^[@\*\&]*/, '')
|
55
|
-
return [] if
|
56
|
-
return [] unless
|
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
|
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
|
-
|
56
|
-
|
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
|
60
|
+
return [] if accept_names.include?(full_name)
|
61
61
|
var = name.gsub(/^[@\*\&]*/, '')
|
62
|
-
return [] if
|
63
|
-
return [] unless
|
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
|
-
|
51
|
-
|
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 == '*' ||
|
67
|
-
|
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
|
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
|
-
|
55
|
-
|
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
|
70
|
-
|
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
|
@@ -82,7 +82,7 @@ module Reek
|
|
82
82
|
@syntax_tree ||=
|
83
83
|
begin
|
84
84
|
begin
|
85
|
-
ast, comments =
|
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.
|
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.
|
49
|
+
configuration.path_excluded?(path)
|
49
50
|
end
|
50
51
|
|
51
52
|
def print_no_such_file_error(path)
|
data/lib/reek/spec.rb
CHANGED
@@ -87,7 +87,7 @@ module Reek
|
|
87
87
|
#
|
88
88
|
def reek_of(smell_category,
|
89
89
|
smell_details = {},
|
90
|
-
configuration = Configuration::AppConfiguration.
|
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.
|
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.
|
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.
|
11
|
+
def initialize(configuration = Configuration::AppConfiguration.default)
|
12
12
|
@configuration = configuration
|
13
13
|
end
|
14
14
|
|
15
15
|
def matches?(actual)
|
16
|
-
|
17
|
-
|
16
|
+
self.examiner = Examiner.new(actual, configuration: configuration)
|
17
|
+
examiner.smelly?
|
18
18
|
end
|
19
19
|
|
20
20
|
def failure_message
|
21
|
-
"Expected #{
|
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(
|
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.
|
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
|
-
|
21
|
-
|
22
|
-
|
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 #{
|
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 #{
|
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:
|
14
|
+
matches_examiner?(Examiner.new(actual, configuration: configuration))
|
14
15
|
end
|
15
16
|
|
16
17
|
def matches_examiner?(examiner)
|
17
|
-
|
18
|
-
|
19
|
-
return false if
|
20
|
-
|
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(
|
25
|
-
"Expected #{
|
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 #{
|
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
|