reek 5.6.0 → 6.0.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -1
- data/.simplecov +1 -0
- data/.travis.yml +12 -11
- data/CHANGELOG.md +8 -0
- data/Dockerfile +1 -0
- data/Gemfile +15 -17
- data/README.md +1 -7
- data/bin/code_climate_reek +12 -2
- data/docs/Attribute.md +1 -1
- data/docs/Control-Couple.md +1 -1
- data/docs/Nil-Check.md +4 -1
- data/features/command_line_interface/options.feature +2 -3
- data/features/reports/codeclimate.feature +2 -2
- data/features/reports/json.feature +3 -3
- data/features/reports/reports.feature +4 -4
- data/features/reports/yaml.feature +3 -3
- data/features/step_definitions/reek_steps.rb +4 -0
- data/lib/reek/ast/sexp_extensions/arguments.rb +11 -0
- data/lib/reek/cli/options.rb +2 -2
- data/lib/reek/code_comment.rb +36 -29
- data/lib/reek/errors/legacy_comment_separator_error.rb +36 -0
- data/lib/reek/report.rb +5 -7
- data/lib/reek/report/code_climate/code_climate_report.rb +2 -1
- data/lib/reek/report/simple_warning_formatter.rb +0 -7
- data/lib/reek/smell_detectors/base_detector.rb +0 -9
- data/lib/reek/smell_detectors/data_clump.rb +23 -56
- data/lib/reek/smell_detectors/nil_check.rb +1 -12
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +5 -6
- data/spec/reek/ast/sexp_extensions_spec.rb +15 -33
- data/spec/reek/code_comment_spec.rb +23 -21
- data/spec/reek/context_builder_spec.rb +110 -113
- data/spec/reek/smell_detectors/base_detector_spec.rb +0 -10
- data/spec/reek/smell_detectors/data_clump_spec.rb +14 -0
- data/spec/reek/smell_detectors/missing_safe_method_spec.rb +8 -2
- data/spec/reek/smell_detectors/nil_check_spec.rb +3 -3
- data/spec/reek/source/source_code_spec.rb +13 -0
- data/spec/spec_helper.rb +1 -0
- metadata +6 -18
@@ -3,42 +3,126 @@ require_lib 'reek/context_builder'
|
|
3
3
|
|
4
4
|
RSpec.describe Reek::ContextBuilder do
|
5
5
|
describe '#context_tree' do
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
context 'with some simple example code' do
|
7
|
+
let(:walker) do
|
8
|
+
code = 'class Car; def drive; end; end'
|
9
|
+
described_class.new(syntax_tree(code))
|
10
|
+
end
|
11
|
+
let(:context_tree) { walker.context_tree }
|
12
|
+
let(:module_context) { context_tree.children.first }
|
13
|
+
let(:method_context) { module_context.children.first }
|
14
|
+
|
15
|
+
describe 'the starting node' do
|
16
|
+
it 'is a root node' do
|
17
|
+
expect(context_tree.type).to eq(:root)
|
18
|
+
expect(context_tree).to be_a(Reek::Context::RootContext)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has one module_context child' do
|
22
|
+
aggregate_failures do
|
23
|
+
expect(context_tree.children.count).to eq 1
|
24
|
+
expect(module_context).to be_a(Reek::Context::ModuleContext)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'the module node' do
|
30
|
+
it 'has one method_context child' do
|
31
|
+
aggregate_failures do
|
32
|
+
expect(method_context).to be_a(Reek::Context::MethodContext)
|
33
|
+
expect(module_context.children.size).to eq(1)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'holds a reference to the parent context' do
|
38
|
+
expect(method_context.parent).to eq(module_context)
|
39
|
+
end
|
40
|
+
end
|
9
41
|
end
|
10
|
-
let(:context_tree) { walker.context_tree }
|
11
|
-
let(:module_context) { context_tree.children.first }
|
12
|
-
let(:method_context) { module_context.children.first }
|
13
42
|
|
14
|
-
it '
|
15
|
-
|
16
|
-
|
43
|
+
it 'creates the proper context for all kinds of singleton methods' do
|
44
|
+
src = <<-RUBY
|
45
|
+
class Car
|
46
|
+
def self.start; end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
def drive; end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
RUBY
|
53
|
+
|
54
|
+
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
55
|
+
context_tree = described_class.new(syntax_tree).context_tree
|
56
|
+
|
57
|
+
class_node = context_tree.children.first
|
58
|
+
start_method = class_node.children.first
|
59
|
+
drive_method = class_node.children.last
|
60
|
+
|
61
|
+
expect(start_method).to be_instance_of Reek::Context::SingletonMethodContext
|
62
|
+
expect(drive_method).to be_instance_of Reek::Context::SingletonMethodContext
|
17
63
|
end
|
18
64
|
|
19
|
-
it '
|
20
|
-
|
65
|
+
it 'returns something sensible for nested metaclasses' do
|
66
|
+
src = <<-RUBY
|
67
|
+
class Foo
|
68
|
+
class << self
|
69
|
+
class << self
|
70
|
+
def bar; end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
RUBY
|
75
|
+
|
76
|
+
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
77
|
+
context_tree = described_class.new(syntax_tree).context_tree
|
78
|
+
|
79
|
+
class_context = context_tree.children.first
|
80
|
+
method_context = class_context.children.first
|
81
|
+
|
82
|
+
expect(method_context).to be_instance_of Reek::Context::SingletonMethodContext
|
83
|
+
expect(method_context.parent).to eq class_context
|
21
84
|
end
|
22
85
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
86
|
+
it 'returns something sensible for nested method definitions' do
|
87
|
+
src = <<-RUBY
|
88
|
+
class Foo
|
89
|
+
def foo
|
90
|
+
def bar
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
RUBY
|
27
95
|
|
28
|
-
|
29
|
-
|
30
|
-
|
96
|
+
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
97
|
+
context_tree = described_class.new(syntax_tree).context_tree
|
98
|
+
|
99
|
+
class_context = context_tree.children.first
|
100
|
+
foo_context = class_context.children.first
|
101
|
+
|
102
|
+
bar_context = foo_context.children.first
|
103
|
+
expect(bar_context).to be_instance_of Reek::Context::MethodContext
|
104
|
+
expect(bar_context.parent).to eq foo_context
|
31
105
|
end
|
32
106
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
107
|
+
it 'returns something sensible for method definitions nested in singleton methods' do
|
108
|
+
src = <<-RUBY
|
109
|
+
class Foo
|
110
|
+
def self.foo
|
111
|
+
def bar
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
RUBY
|
38
116
|
|
39
|
-
|
40
|
-
|
41
|
-
|
117
|
+
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
118
|
+
context_tree = described_class.new(syntax_tree).context_tree
|
119
|
+
|
120
|
+
class_context = context_tree.children.first
|
121
|
+
foo_context = class_context.children.first
|
122
|
+
|
123
|
+
bar_context = foo_context.children.first
|
124
|
+
expect(bar_context).to be_instance_of Reek::Context::SingletonMethodContext
|
125
|
+
expect(bar_context.parent).to eq foo_context
|
42
126
|
end
|
43
127
|
end
|
44
128
|
|
@@ -370,91 +454,4 @@ RSpec.describe Reek::ContextBuilder do
|
|
370
454
|
expect(nested_baz_context.visibility).to eq :public
|
371
455
|
end
|
372
456
|
end
|
373
|
-
|
374
|
-
describe '#context_tree' do
|
375
|
-
it 'creates the proper context for all kinds of singleton methods' do
|
376
|
-
src = <<-RUBY
|
377
|
-
class Car
|
378
|
-
def self.start; end
|
379
|
-
|
380
|
-
class << self
|
381
|
-
def drive; end
|
382
|
-
end
|
383
|
-
end
|
384
|
-
RUBY
|
385
|
-
|
386
|
-
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
387
|
-
context_tree = described_class.new(syntax_tree).context_tree
|
388
|
-
|
389
|
-
class_node = context_tree.children.first
|
390
|
-
start_method = class_node.children.first
|
391
|
-
drive_method = class_node.children.last
|
392
|
-
|
393
|
-
expect(start_method).to be_instance_of Reek::Context::SingletonMethodContext
|
394
|
-
expect(drive_method).to be_instance_of Reek::Context::SingletonMethodContext
|
395
|
-
end
|
396
|
-
|
397
|
-
it 'returns something sensible for nested metaclasses' do
|
398
|
-
src = <<-RUBY
|
399
|
-
class Foo
|
400
|
-
class << self
|
401
|
-
class << self
|
402
|
-
def bar; end
|
403
|
-
end
|
404
|
-
end
|
405
|
-
end
|
406
|
-
RUBY
|
407
|
-
|
408
|
-
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
409
|
-
context_tree = described_class.new(syntax_tree).context_tree
|
410
|
-
|
411
|
-
class_context = context_tree.children.first
|
412
|
-
method_context = class_context.children.first
|
413
|
-
|
414
|
-
expect(method_context).to be_instance_of Reek::Context::SingletonMethodContext
|
415
|
-
expect(method_context.parent).to eq class_context
|
416
|
-
end
|
417
|
-
|
418
|
-
it 'returns something sensible for nested method definitions' do
|
419
|
-
src = <<-RUBY
|
420
|
-
class Foo
|
421
|
-
def foo
|
422
|
-
def bar
|
423
|
-
end
|
424
|
-
end
|
425
|
-
end
|
426
|
-
RUBY
|
427
|
-
|
428
|
-
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
429
|
-
context_tree = described_class.new(syntax_tree).context_tree
|
430
|
-
|
431
|
-
class_context = context_tree.children.first
|
432
|
-
foo_context = class_context.children.first
|
433
|
-
|
434
|
-
bar_context = foo_context.children.first
|
435
|
-
expect(bar_context).to be_instance_of Reek::Context::MethodContext
|
436
|
-
expect(bar_context.parent).to eq foo_context
|
437
|
-
end
|
438
|
-
|
439
|
-
it 'returns something sensible for method definitions nested in singleton methods' do
|
440
|
-
src = <<-RUBY
|
441
|
-
class Foo
|
442
|
-
def self.foo
|
443
|
-
def bar
|
444
|
-
end
|
445
|
-
end
|
446
|
-
end
|
447
|
-
RUBY
|
448
|
-
|
449
|
-
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
450
|
-
context_tree = described_class.new(syntax_tree).context_tree
|
451
|
-
|
452
|
-
class_context = context_tree.children.first
|
453
|
-
foo_context = class_context.children.first
|
454
|
-
|
455
|
-
bar_context = foo_context.children.first
|
456
|
-
expect(bar_context).to be_instance_of Reek::Context::SingletonMethodContext
|
457
|
-
expect(bar_context.parent).to eq foo_context
|
458
|
-
end
|
459
|
-
end
|
460
457
|
end
|
@@ -31,16 +31,6 @@ RSpec.describe Reek::SmellDetectors::BaseDetector do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
describe '.valid_detector?' do
|
35
|
-
it 'returns true for a valid detector' do
|
36
|
-
expect(described_class.valid_detector?('DuplicateMethodCall')).to be true
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'returns false for an invalid detector' do
|
40
|
-
expect(described_class.valid_detector?('Unknown')).to be false
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
34
|
describe '.to_detector' do
|
45
35
|
it 'returns the right detector' do
|
46
36
|
expect(described_class.to_detector('DuplicateMethodCall')).to eq(Reek::SmellDetectors::DuplicateMethodCall)
|
@@ -76,6 +76,20 @@ RSpec.describe Reek::SmellDetectors::DataClump do
|
|
76
76
|
parameters: ['echo', 'foxtrot'])
|
77
77
|
end
|
78
78
|
|
79
|
+
it 'reports arguments in alphabetical order even if they are never used that way' do
|
80
|
+
src = <<-RUBY
|
81
|
+
#{scope} Alfa
|
82
|
+
def bravo (foxtrot, echo); end
|
83
|
+
def charlie(foxtrot, echo); end
|
84
|
+
def delta (foxtrot, echo); end
|
85
|
+
end
|
86
|
+
RUBY
|
87
|
+
|
88
|
+
expect(src).to reek_of(:DataClump,
|
89
|
+
count: 3,
|
90
|
+
parameters: ['echo', 'foxtrot'])
|
91
|
+
end
|
92
|
+
|
79
93
|
it 'reports parameter sets that are > 2' do
|
80
94
|
src = <<-RUBY
|
81
95
|
#{scope} Alfa
|
@@ -50,13 +50,19 @@ RSpec.describe Reek::SmellDetectors::MissingSafeMethod do
|
|
50
50
|
|
51
51
|
it 'does not report methods we excluded via comment' do
|
52
52
|
source = <<-RUBY
|
53
|
-
# :reek:MissingSafeMethod
|
53
|
+
# :reek:MissingSafeMethod { exclude: [ bravo! ] }
|
54
54
|
class Alfa
|
55
55
|
def bravo!
|
56
56
|
end
|
57
|
+
|
58
|
+
def charlie!
|
59
|
+
end
|
57
60
|
end
|
58
61
|
RUBY
|
59
62
|
|
60
|
-
|
63
|
+
aggregate_failures do
|
64
|
+
expect(source).not_to reek_of(:MissingSafeMethod, name: 'bravo!')
|
65
|
+
expect(source).to reek_of(:MissingSafeMethod, name: 'charlie!')
|
66
|
+
end
|
61
67
|
end
|
62
68
|
end
|
@@ -76,14 +76,14 @@ RSpec.describe Reek::SmellDetectors::NilCheck do
|
|
76
76
|
expect(src).to reek_of(:NilCheck)
|
77
77
|
end
|
78
78
|
|
79
|
-
it '
|
79
|
+
it 'does not report when scope uses &.' do
|
80
80
|
src = <<-RUBY
|
81
81
|
def alfa(bravo)
|
82
82
|
bravo&.charlie
|
83
83
|
end
|
84
84
|
RUBY
|
85
85
|
|
86
|
-
expect(src).
|
86
|
+
expect(src).not_to reek_of(:NilCheck)
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'reports all lines when scope uses multiple nilchecks' do
|
@@ -95,6 +95,6 @@ RSpec.describe Reek::SmellDetectors::NilCheck do
|
|
95
95
|
end
|
96
96
|
RUBY
|
97
97
|
|
98
|
-
expect(src).to reek_of(:NilCheck, lines: [2, 3
|
98
|
+
expect(src).to reek_of(:NilCheck, lines: [2, 3])
|
99
99
|
end
|
100
100
|
end
|
@@ -62,5 +62,18 @@ RSpec.describe Reek::Source::SourceCode do
|
|
62
62
|
expect { src.syntax_tree }.to raise_error error_class, error_message
|
63
63
|
end
|
64
64
|
end
|
65
|
+
|
66
|
+
if RUBY_VERSION >= '2.7'
|
67
|
+
context 'with ruby 2.7 syntax' do
|
68
|
+
context 'with forward_args (`...`)' do
|
69
|
+
let(:source_code) { described_class.new(source: 'def alpha(...) bravo(...); end') }
|
70
|
+
|
71
|
+
it 'returns a :forward_args node' do
|
72
|
+
result = source_code.syntax_tree
|
73
|
+
expect(result.children[1].type).to eq(:forward_args)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
65
78
|
end
|
66
79
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reek
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Rutherford
|
@@ -11,22 +11,8 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2020-
|
14
|
+
date: 2020-03-30 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
17
|
-
name: codeclimate-engine-rb
|
18
|
-
requirement: !ruby/object:Gem::Requirement
|
19
|
-
requirements:
|
20
|
-
- - "~>"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 0.4.0
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 0.4.0
|
30
16
|
- !ruby/object:Gem::Dependency
|
31
17
|
name: kwalify
|
32
18
|
requirement: !ruby/object:Gem::Requirement
|
@@ -281,6 +267,7 @@ files:
|
|
281
267
|
- lib/reek/errors/encoding_error.rb
|
282
268
|
- lib/reek/errors/garbage_detector_configuration_in_comment_error.rb
|
283
269
|
- lib/reek/errors/incomprehensible_source_error.rb
|
270
|
+
- lib/reek/errors/legacy_comment_separator_error.rb
|
284
271
|
- lib/reek/errors/syntax_error.rb
|
285
272
|
- lib/reek/examiner.rb
|
286
273
|
- lib/reek/logging_error_handler.rb
|
@@ -492,14 +479,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
492
479
|
requirements:
|
493
480
|
- - ">="
|
494
481
|
- !ruby/object:Gem::Version
|
495
|
-
version: 2.
|
482
|
+
version: 2.4.0
|
496
483
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
497
484
|
requirements:
|
498
485
|
- - ">="
|
499
486
|
- !ruby/object:Gem::Version
|
500
487
|
version: '0'
|
501
488
|
requirements: []
|
502
|
-
|
489
|
+
rubyforge_project:
|
490
|
+
rubygems_version: 2.7.7
|
503
491
|
signing_key:
|
504
492
|
specification_version: 4
|
505
493
|
summary: Code smell detector for Ruby
|