reek 3.4.0 → 3.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/features/step_definitions/reek_steps.rb +19 -16
- data/lib/reek/ast/sexp_extensions.rb +17 -8
- data/lib/reek/cli/application.rb +21 -12
- data/lib/reek/cli/option_interpreter.rb +1 -6
- data/lib/reek/cli/options.rb +32 -22
- data/lib/reek/report/location_formatter.rb +11 -5
- data/lib/reek/smells/smell_warning.rb +10 -2
- data/lib/reek/smells/uncommunicative_method_name.rb +25 -21
- data/lib/reek/smells/uncommunicative_parameter_name.rb +14 -15
- data/lib/reek/spec/should_reek_of.rb +44 -9
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +2 -2
- data/spec/reek/ast/node_spec.rb +1 -1
- data/spec/reek/ast/object_refs_spec.rb +1 -1
- data/spec/reek/ast/reference_collector_spec.rb +1 -1
- data/spec/reek/ast/sexp_extensions_spec.rb +49 -2
- data/spec/reek/ast/sexp_formatter_spec.rb +1 -1
- data/spec/reek/cli/option_interpreter_spec.rb +7 -7
- data/spec/reek/cli/options_spec.rb +27 -19
- data/spec/reek/cli/warning_collector_spec.rb +2 -2
- data/spec/reek/code_comment_spec.rb +1 -1
- data/spec/reek/configuration/app_configuration_spec.rb +4 -4
- data/spec/reek/configuration/default_directive_spec.rb +1 -1
- data/spec/reek/configuration/directory_directives_spec.rb +1 -1
- data/spec/reek/configuration/excluded_paths_spec.rb +1 -1
- data/spec/reek/context/code_context_spec.rb +2 -2
- data/spec/reek/context/method_context_spec.rb +1 -1
- data/spec/reek/context/module_context_spec.rb +2 -2
- data/spec/reek/context/root_context_spec.rb +1 -1
- data/spec/reek/context/singleton_method_context_spec.rb +1 -1
- data/spec/reek/examiner_spec.rb +1 -1
- data/spec/reek/report/html_report_spec.rb +2 -2
- data/spec/reek/report/json_report_spec.rb +3 -3
- data/spec/reek/report/location_formatter_spec.rb +30 -0
- data/spec/reek/report/text_report_spec.rb +4 -4
- data/spec/reek/report/xml_report_spec.rb +2 -2
- data/spec/reek/report/yaml_report_spec.rb +3 -3
- data/spec/reek/smells/attribute_spec.rb +1 -1
- data/spec/reek/smells/boolean_parameter_spec.rb +1 -1
- data/spec/reek/smells/class_variable_spec.rb +2 -2
- data/spec/reek/smells/control_parameter_spec.rb +1 -1
- data/spec/reek/smells/data_clump_spec.rb +1 -1
- data/spec/reek/smells/duplicate_method_call_spec.rb +3 -3
- data/spec/reek/smells/feature_envy_spec.rb +2 -2
- data/spec/reek/smells/irresponsible_module_spec.rb +2 -2
- data/spec/reek/smells/long_parameter_list_spec.rb +2 -2
- data/spec/reek/smells/long_yield_list_spec.rb +2 -2
- data/spec/reek/smells/module_initialize_spec.rb +1 -1
- data/spec/reek/smells/nested_iterators_spec.rb +1 -1
- data/spec/reek/smells/nil_check_spec.rb +2 -2
- data/spec/reek/smells/prima_donna_method_spec.rb +1 -1
- data/spec/reek/smells/repeated_conditional_spec.rb +3 -3
- data/spec/reek/smells/smell_configuration_spec.rb +1 -1
- data/spec/reek/smells/smell_repository_spec.rb +2 -2
- data/spec/reek/smells/smell_warning_spec.rb +1 -1
- data/spec/reek/smells/too_many_instance_variables_spec.rb +1 -1
- data/spec/reek/smells/too_many_methods_spec.rb +1 -1
- data/spec/reek/smells/too_many_statements_spec.rb +1 -1
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +2 -2
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +2 -2
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +2 -2
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
- data/spec/reek/smells/unused_parameters_spec.rb +1 -1
- data/spec/reek/smells/utility_function_spec.rb +2 -2
- data/spec/reek/source/source_code_spec.rb +1 -1
- data/spec/reek/source/source_locator_spec.rb +2 -2
- data/spec/reek/spec/should_reek_of_spec.rb +90 -37
- data/spec/reek/spec/should_reek_only_of_spec.rb +1 -1
- data/spec/reek/spec/should_reek_spec.rb +1 -1
- data/spec/reek/tree_dresser_spec.rb +2 -2
- data/spec/reek/tree_walker_spec.rb +2 -2
- data/spec/spec_helper.rb +6 -0
- metadata +7 -6
@@ -18,14 +18,9 @@ module Reek
|
|
18
18
|
#
|
19
19
|
# See {file:docs/Uncommunicative-Parameter-Name.md} for details.
|
20
20
|
class UncommunicativeParameterName < SmellDetector
|
21
|
-
# The name of the config field that lists the regexps of
|
22
|
-
# smelly names to be reported.
|
23
21
|
REJECT_KEY = 'reject'
|
24
22
|
DEFAULT_REJECT_PATTERNS = [/^.$/, /[0-9]$/, /[A-Z]/, /^_/]
|
25
23
|
|
26
|
-
# The name of the config field that lists the specific names that are
|
27
|
-
# to be treated as exceptions; these names will not be reported as
|
28
|
-
# uncommunicative.
|
29
24
|
ACCEPT_KEY = 'accept'
|
30
25
|
DEFAULT_ACCEPT_NAMES = []
|
31
26
|
|
@@ -45,14 +40,15 @@ module Reek
|
|
45
40
|
#
|
46
41
|
# @return [Array<SmellWarning>]
|
47
42
|
#
|
48
|
-
def examine_context(
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
def examine_context(context)
|
44
|
+
expression = context.exp
|
45
|
+
expression.parameter_names.select do |name|
|
46
|
+
sanitized_name = sanitize name
|
47
|
+
uncommunicative_parameter_name?(name: sanitized_name, context: context)
|
52
48
|
end.map do |name|
|
53
49
|
smell_warning(
|
54
|
-
context:
|
55
|
-
lines: [
|
50
|
+
context: context,
|
51
|
+
lines: [expression.line],
|
56
52
|
message: "has the parameter name '#{name}'",
|
57
53
|
parameters: { name: name.to_s })
|
58
54
|
end
|
@@ -60,10 +56,13 @@ module Reek
|
|
60
56
|
|
61
57
|
private
|
62
58
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
def uncommunicative_parameter_name?(name: raise, context: raise)
|
60
|
+
!acceptable_name?(name: name, context: context) && context.uses_param?(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def acceptable_name?(name: raise, context: raise)
|
64
|
+
accept_names(context).any? { |accept_name| name == accept_name } ||
|
65
|
+
reject_patterns(context).none? { |pattern| name.match pattern }
|
67
66
|
end
|
68
67
|
|
69
68
|
def reject_patterns(context)
|
@@ -7,6 +7,12 @@ module Reek
|
|
7
7
|
# code smell.
|
8
8
|
#
|
9
9
|
class ShouldReekOf
|
10
|
+
attr_reader :failure_message, :failure_message_when_negated
|
11
|
+
|
12
|
+
private_attr_reader :configuration, :smell_category, :smell_details
|
13
|
+
private_attr_writer :failure_message, :failure_message_when_negated
|
14
|
+
private_attr_accessor :examiner
|
15
|
+
|
10
16
|
def initialize(smell_category,
|
11
17
|
smell_details = {},
|
12
18
|
configuration = Configuration::AppConfiguration.default)
|
@@ -17,22 +23,51 @@ module Reek
|
|
17
23
|
|
18
24
|
def matches?(actual)
|
19
25
|
self.examiner = Examiner.new(actual, configuration: configuration)
|
20
|
-
|
21
|
-
|
26
|
+
set_failure_messages
|
27
|
+
matching_smell_types? && matching_smell_details?
|
22
28
|
end
|
23
29
|
|
24
|
-
|
25
|
-
|
30
|
+
private
|
31
|
+
|
32
|
+
def set_failure_messages
|
33
|
+
# We set the failure messages for non-matching smell type unconditionally since we
|
34
|
+
# need that in any case for "failure_message_when_negated" below.
|
35
|
+
# Depending on the existence of matching smell type we check for matching
|
36
|
+
# smell details and then overwrite our failure messages conditionally.
|
37
|
+
set_failure_messages_for_smell_type
|
38
|
+
set_failure_messages_for_smell_details if matching_smell_types? && !matching_smell_details?
|
26
39
|
end
|
27
40
|
|
28
|
-
def
|
29
|
-
|
41
|
+
def matching_smell_types
|
42
|
+
@matching_smell_types ||= examiner.smells.
|
43
|
+
select { |warning| warning.matches_smell_type?(smell_category) }
|
30
44
|
end
|
31
45
|
|
32
|
-
|
46
|
+
def matching_smell_types?
|
47
|
+
matching_smell_types.any?
|
48
|
+
end
|
33
49
|
|
34
|
-
|
35
|
-
|
50
|
+
def matching_smell_details?
|
51
|
+
matching_smell_types.any? { |warning| warning.matches_smell_details?(smell_details) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_failure_messages_for_smell_type
|
55
|
+
self.failure_message = "Expected #{origin} to reek of #{smell_category}, "\
|
56
|
+
'but it didn\'t'
|
57
|
+
self.failure_message_when_negated = "Expected #{origin} not to reek "\
|
58
|
+
"of #{smell_category}, but it did"
|
59
|
+
end
|
60
|
+
|
61
|
+
def set_failure_messages_for_smell_details
|
62
|
+
self.failure_message = "Expected #{origin} to reek of #{smell_category} "\
|
63
|
+
"(which it did) with smell details #{smell_details}, which it didn't"
|
64
|
+
self.failure_message_when_negated = "Expected #{origin} not to reek of "\
|
65
|
+
"#{smell_category} with smell details #{smell_details}, but it did"
|
66
|
+
end
|
67
|
+
|
68
|
+
def origin
|
69
|
+
examiner.description
|
70
|
+
end
|
36
71
|
|
37
72
|
# :reek:UtilityFunction
|
38
73
|
def normalize(smell_category_or_type)
|
data/lib/reek/version.rb
CHANGED
data/reek.gemspec
CHANGED
@@ -28,12 +28,12 @@ Gem::Specification.new do |s|
|
|
28
28
|
s.add_runtime_dependency 'unparser', '~> 0.2.2'
|
29
29
|
|
30
30
|
s.add_development_dependency 'activesupport', '~> 4.2'
|
31
|
-
s.add_development_dependency 'aruba', '~> 0.
|
31
|
+
s.add_development_dependency 'aruba', '~> 0.9.0'
|
32
32
|
s.add_development_dependency 'ataru', '~> 0.2.0'
|
33
33
|
s.add_development_dependency 'bundler', '~> 1.1'
|
34
34
|
s.add_development_dependency 'cucumber', '~> 2.0'
|
35
35
|
s.add_development_dependency 'factory_girl', '~> 4.0'
|
36
36
|
s.add_development_dependency 'rake', '~> 10.0'
|
37
37
|
s.add_development_dependency 'rspec', '~> 3.0'
|
38
|
-
s.add_development_dependency 'rubocop', '~> 0.
|
38
|
+
s.add_development_dependency 'rubocop', '~> 0.34.0'
|
39
39
|
end
|
data/spec/reek/ast/node_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
|
-
|
2
|
+
require_lib 'reek/ast/sexp_extensions'
|
3
3
|
|
4
4
|
RSpec.describe Reek::AST::SexpExtensions::DefNode do
|
5
5
|
context 'with no parameters' do
|
@@ -231,6 +231,22 @@ RSpec.describe Reek::AST::SexpExtensions::DefsNode do
|
|
231
231
|
end
|
232
232
|
end
|
233
233
|
|
234
|
+
RSpec.describe Reek::AST::SexpExtensions::LvarNode do
|
235
|
+
let(:node) { sexp(:lvar, :foo) }
|
236
|
+
|
237
|
+
describe '#simple_name' do
|
238
|
+
it 'returns the lvar’s name' do
|
239
|
+
expect(node.simple_name).to eq(:foo)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe '#var_name' do
|
244
|
+
it 'returns the lvar’s name' do
|
245
|
+
expect(node.var_name).to eq(:foo)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
234
250
|
RSpec.describe Reek::AST::SexpExtensions::SendNode do
|
235
251
|
context 'with no parameters' do
|
236
252
|
let(:node) { sexp(:send, nil, :hello) }
|
@@ -238,6 +254,26 @@ RSpec.describe Reek::AST::SexpExtensions::SendNode do
|
|
238
254
|
it 'has no argument names' do
|
239
255
|
expect(node.arg_names).to eq []
|
240
256
|
end
|
257
|
+
|
258
|
+
it 'is not considered to be a writable attr' do
|
259
|
+
expect(sexp(:send, nil, :attr).attr_with_writable_flag?).to be_falsey
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context 'when it’s ‘new’ with no parameters and no receiver' do
|
264
|
+
let(:bare_new) { sexp(:send, nil, :new) }
|
265
|
+
|
266
|
+
it 'is not considered to be a module creation call' do
|
267
|
+
expect(bare_new.module_creation_call?).to be_falsey
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'is not considered to have a module creation receiver' do
|
271
|
+
expect(bare_new.module_creation_receiver?).to be_falsey
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'is considered to be an object creation call' do
|
275
|
+
expect(bare_new.object_creation_call?).to be_truthy
|
276
|
+
end
|
241
277
|
end
|
242
278
|
|
243
279
|
context 'with 1 literal parameter' do
|
@@ -264,6 +300,10 @@ RSpec.describe Reek::AST::SexpExtensions::BlockNode do
|
|
264
300
|
it 'has no parameter names' do
|
265
301
|
expect(node.parameter_names).to eq []
|
266
302
|
end
|
303
|
+
|
304
|
+
it 'has a name' do
|
305
|
+
expect(node.simple_name).to eq(:block)
|
306
|
+
end
|
267
307
|
end
|
268
308
|
|
269
309
|
context 'with 1 parameter' do
|
@@ -337,7 +377,14 @@ RSpec.describe Reek::AST::SexpExtensions::CasgnNode do
|
|
337
377
|
end
|
338
378
|
|
339
379
|
it 'does not define a module' do
|
340
|
-
expect(subject.defines_module?).to
|
380
|
+
expect(subject.defines_module?).to be_falsey
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
context 'with implicit receiver to new' do
|
385
|
+
it 'does not define a module' do
|
386
|
+
exp = sexp(:casgn, nil, :Foo, sexp(:send, nil, :new))
|
387
|
+
expect(exp.defines_module?).to be_falsey
|
341
388
|
end
|
342
389
|
end
|
343
390
|
end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require_lib 'reek/cli/options'
|
4
|
+
require_lib 'reek/cli/option_interpreter'
|
5
|
+
require_lib 'reek/report/report'
|
5
6
|
|
6
7
|
RSpec.describe Reek::CLI::OptionInterpreter do
|
7
8
|
describe '#reporter' do
|
8
|
-
let(:instance) { Reek::CLI::OptionInterpreter.new(options) }
|
9
|
-
|
10
9
|
context 'with a valid set of options' do
|
11
10
|
let(:options) do
|
12
|
-
|
13
|
-
location_format: :plain)
|
11
|
+
Reek::CLI::Options.new.parse
|
14
12
|
end
|
13
|
+
subject { described_class.new(options) }
|
14
|
+
|
15
15
|
it 'returns an object of the correct subclass of Report::Base' do
|
16
|
-
expect(
|
16
|
+
expect(subject.reporter).to be_instance_of Reek::Report::TextReport
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -1,28 +1,36 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
require_relative '../../../lib/reek/cli/options'
|
2
|
+
require_lib 'reek/cli/options'
|
4
3
|
|
5
4
|
RSpec.describe Reek::CLI::Options do
|
6
|
-
describe '#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
allow($stdout).to receive_messages(tty?: false)
|
11
|
-
expect(options.colored).to be false
|
12
|
-
end
|
5
|
+
describe '#initialize' do
|
6
|
+
it 'sets a valid default value for report_format' do
|
7
|
+
expect(subject.report_format).to eq :text
|
8
|
+
end
|
13
9
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
it 'sets a valid default value for location_format' do
|
11
|
+
expect(subject.location_format).to eq :numbers
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'enables colors when stdout is a TTY' do
|
15
|
+
allow($stdout).to receive_messages(tty?: false)
|
16
|
+
expect(subject.colored).to be false
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
it 'does not enable colors when stdout is not a TTY' do
|
20
|
+
allow($stdout).to receive_messages(tty?: true)
|
21
|
+
expect(subject.colored).to be true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'parse' do
|
26
|
+
it 'raises on invalid argument in ARGV' do
|
27
|
+
options = described_class.new
|
28
|
+
options.argv = ['-z']
|
29
|
+
expect { options.parse }.to raise_error(OptionParser::InvalidOption)
|
30
|
+
end
|
22
31
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
32
|
+
it 'returns self' do
|
33
|
+
expect(subject.parse).to be_a(described_class)
|
26
34
|
end
|
27
35
|
end
|
28
36
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
|
2
|
+
require_lib 'reek/cli/warning_collector'
|
3
|
+
require_lib 'reek/smells/smell_warning'
|
4
4
|
|
5
5
|
RSpec.describe Reek::CLI::WarningCollector do
|
6
6
|
let(:collector) { described_class.new }
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require_relative '../../spec_helper'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
require_lib 'reek/configuration/app_configuration'
|
4
|
+
require_lib 'reek/configuration/directory_directives'
|
5
|
+
require_lib 'reek/configuration/default_directive'
|
6
|
+
require_lib 'reek/configuration/excluded_paths'
|
7
7
|
|
8
8
|
RSpec.describe Reek::Configuration::AppConfiguration do
|
9
9
|
describe '#new' do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
|
2
|
+
require_lib 'reek/context/method_context'
|
3
|
+
require_lib 'reek/context/module_context'
|
4
4
|
|
5
5
|
RSpec.describe Reek::Context::CodeContext do
|
6
6
|
context 'name recognition' do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
|
-
|
3
|
-
|
2
|
+
require_lib 'reek/context/module_context'
|
3
|
+
require_lib 'reek/context/root_context'
|
4
4
|
|
5
5
|
RSpec.describe Reek::Context::ModuleContext do
|
6
6
|
it 'should report module name for smell in method' do
|