reek 5.4.1 → 6.0.2
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 +8 -6
- data/.rubocop_todo.yml +25 -20
- data/.simplecov +1 -0
- data/.travis.yml +17 -11
- data/CHANGELOG.md +31 -3
- data/Dockerfile +1 -0
- data/Gemfile +14 -17
- data/README.md +15 -11
- data/bin/code_climate_reek +12 -2
- data/docs/Attribute.md +1 -1
- data/docs/Boolean-Parameter.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/configuration_files/schema_validation.feature +1 -1
- 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 +5 -1
- data/features/step_definitions/sample_file_steps.rb +2 -2
- data/features/support/env.rb +1 -2
- data/lib/reek.rb +1 -0
- data/lib/reek/ast/sexp_extensions/arguments.rb +11 -0
- data/lib/reek/cli/options.rb +3 -3
- data/lib/reek/code_comment.rb +45 -38
- data/lib/reek/configuration/app_configuration.rb +4 -3
- data/lib/reek/configuration/configuration_converter.rb +2 -2
- data/lib/reek/configuration/directory_directives.rb +9 -3
- data/lib/reek/context/module_context.rb +3 -1
- data/lib/reek/errors/legacy_comment_separator_error.rb +36 -0
- data/lib/reek/examiner.rb +3 -3
- data/lib/reek/report.rb +5 -7
- data/lib/reek/report/code_climate/code_climate_configuration.yml +1 -1
- 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/report/text_report.rb +2 -2
- data/lib/reek/smell_detectors/base_detector.rb +1 -9
- data/lib/reek/smell_detectors/boolean_parameter.rb +3 -1
- data/lib/reek/smell_detectors/data_clump.rb +23 -56
- data/lib/reek/smell_detectors/nil_check.rb +1 -12
- data/lib/reek/smell_detectors/subclassed_from_core_class.rb +3 -7
- data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +1 -1
- data/lib/reek/smell_warning.rb +1 -2
- data/lib/reek/source/source_code.rb +3 -2
- data/lib/reek/source/source_locator.rb +13 -10
- data/lib/reek/spec/smell_matcher.rb +2 -1
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +13 -6
- data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +2 -4
- data/spec/quality/documentation_spec.rb +2 -1
- data/spec/reek/ast/sexp_extensions_spec.rb +15 -33
- data/spec/reek/code_comment_spec.rb +41 -42
- data/spec/reek/configuration/directory_directives_spec.rb +6 -0
- data/spec/reek/context_builder_spec.rb +110 -113
- data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +1 -3
- data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +26 -26
- data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +6 -6
- data/spec/reek/report/code_climate/code_climate_report_spec.rb +1 -1
- data/spec/reek/report/json_report_spec.rb +1 -1
- data/spec/reek/report/location_formatter_spec.rb +3 -3
- data/spec/reek/report/text_report_spec.rb +1 -7
- data/spec/reek/report/yaml_report_spec.rb +1 -1
- data/spec/reek/smell_detectors/base_detector_spec.rb +3 -13
- 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/smell_warning_spec.rb +12 -12
- data/spec/reek/source/source_code_spec.rb +13 -0
- data/spec/reek/spec/should_reek_of_spec.rb +0 -1
- data/spec/reek/spec/should_reek_only_of_spec.rb +6 -6
- data/spec/reek/spec/smell_matcher_spec.rb +1 -1
- data/spec/spec_helper.rb +20 -6
- data/tasks/configuration.rake +1 -2
- metadata +15 -25
- data/spec/factories/factories.rb +0 -37
@@ -443,73 +443,55 @@ end
|
|
443
443
|
|
444
444
|
RSpec.describe Reek::AST::SexpExtensions::CasgnNode do
|
445
445
|
describe '#defines_module?' do
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
expect(exp).not_to be_defines_module
|
450
|
-
end
|
446
|
+
it 'is false for single assignment' do
|
447
|
+
exp = sexp(:casgn, nil, :Foo)
|
448
|
+
expect(exp).not_to be_defines_module
|
451
449
|
end
|
452
450
|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
expect(exp).not_to be_defines_module
|
457
|
-
end
|
451
|
+
it 'is false for implicit receiver to new' do
|
452
|
+
exp = sexp(:casgn, nil, :Foo, sexp(:send, nil, :new))
|
453
|
+
expect(exp).not_to be_defines_module
|
458
454
|
end
|
459
455
|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
expect(exp).to be_defines_module
|
465
|
-
end
|
456
|
+
it 'is true for explicit receiver to new' do
|
457
|
+
exp = Reek::Source::SourceCode.from('Foo = Class.new(Bar)').syntax_tree
|
458
|
+
expect(exp).to be_defines_module
|
466
459
|
end
|
467
460
|
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
expect(exp).not_to be_defines_module
|
473
|
-
end
|
461
|
+
it 'is false for assigning a lambda to a constant' do
|
462
|
+
exp = Reek::Source::SourceCode.from('C = ->{}').syntax_tree
|
463
|
+
expect(exp).not_to be_defines_module
|
474
464
|
end
|
475
465
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
expect(exp).not_to be_defines_module
|
481
|
-
end
|
466
|
+
it 'is false for assigning a string to a constant' do
|
467
|
+
exp = Reek::Source::SourceCode.from('C = "hello"').syntax_tree
|
468
|
+
expect(exp).not_to be_defines_module
|
482
469
|
end
|
483
470
|
end
|
484
471
|
|
485
472
|
describe '#superclass' do
|
486
473
|
it 'returns the superclass from the class definition' do
|
487
474
|
exp = Reek::Source::SourceCode.from('Foo = Class.new(Bar)').syntax_tree
|
488
|
-
|
489
475
|
expect(exp.superclass).to eq sexp(:const, nil, :Bar)
|
490
476
|
end
|
491
477
|
|
492
478
|
it 'returns nil in case of no class definition' do
|
493
479
|
exp = Reek::Source::SourceCode.from('Foo = 23').syntax_tree
|
494
|
-
|
495
480
|
expect(exp.superclass).to be_nil
|
496
481
|
end
|
497
482
|
|
498
483
|
it 'returns nil in case of no superclass' do
|
499
484
|
exp = Reek::Source::SourceCode.from('Foo = Class.new').syntax_tree
|
500
|
-
|
501
485
|
expect(exp.superclass).to be_nil
|
502
486
|
end
|
503
487
|
|
504
488
|
it 'returns nothing for a class definition using Struct.new' do
|
505
489
|
exp = Reek::Source::SourceCode.from('Foo = Struct.new("Bar")').syntax_tree
|
506
|
-
|
507
490
|
expect(exp.superclass).to be_nil
|
508
491
|
end
|
509
492
|
|
510
493
|
it 'returns nothing for a constant assigned with a bare method call' do
|
511
494
|
exp = Reek::Source::SourceCode.from('Foo = foo("Bar")').syntax_tree
|
512
|
-
|
513
495
|
expect(exp.superclass).to be_nil
|
514
496
|
end
|
515
497
|
end
|
@@ -3,7 +3,7 @@ require_lib 'reek/code_comment'
|
|
3
3
|
|
4
4
|
RSpec.describe Reek::CodeComment do
|
5
5
|
context 'with an empty comment' do
|
6
|
-
let(:comment) {
|
6
|
+
let(:comment) { build_code_comment(comment: '') }
|
7
7
|
|
8
8
|
it 'is not descriptive' do
|
9
9
|
expect(comment).not_to be_descriptive
|
@@ -16,77 +16,63 @@ RSpec.describe Reek::CodeComment do
|
|
16
16
|
|
17
17
|
describe '#descriptive' do
|
18
18
|
it 'rejects an empty comment' do
|
19
|
-
comment =
|
19
|
+
comment = build_code_comment(comment: '#')
|
20
20
|
expect(comment).not_to be_descriptive
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'rejects a 1-word comment' do
|
24
|
-
comment =
|
24
|
+
comment = build_code_comment(comment: "# alpha\n# ")
|
25
25
|
expect(comment).not_to be_descriptive
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'accepts a 2-word comment' do
|
29
|
-
comment =
|
29
|
+
comment = build_code_comment(comment: '# alpha bravo ')
|
30
30
|
expect(comment).to be_descriptive
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'accepts a multi-word comment' do
|
34
|
-
comment =
|
34
|
+
comment = build_code_comment(comment: "# alpha bravo \n# charlie \n # delta ")
|
35
35
|
expect(comment).to be_descriptive
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
describe 'good comment config' do
|
40
40
|
it 'parses hashed options' do
|
41
|
-
comment = '# :reek:DuplicateMethodCall {
|
42
|
-
config =
|
43
|
-
comment: comment).config
|
41
|
+
comment = '# :reek:DuplicateMethodCall { max_calls: 3 }'
|
42
|
+
config = build_code_comment(comment: comment).config
|
44
43
|
|
45
44
|
expect(config).to include('DuplicateMethodCall')
|
46
|
-
expect(config['DuplicateMethodCall']).to
|
47
|
-
expect(config['DuplicateMethodCall']['
|
48
|
-
end
|
49
|
-
|
50
|
-
it "supports hashed options with the legacy separator ':' after the smell detector" do
|
51
|
-
comment = '# :reek:DuplicateMethodCall: { enabled: false }'
|
52
|
-
config = build(:code_comment,
|
53
|
-
comment: comment).config
|
54
|
-
|
55
|
-
expect(config).to include('DuplicateMethodCall')
|
56
|
-
expect(config['DuplicateMethodCall']).to include('enabled')
|
57
|
-
expect(config['DuplicateMethodCall']['enabled']).to be_falsey
|
45
|
+
expect(config['DuplicateMethodCall']).to have_key 'max_calls'
|
46
|
+
expect(config['DuplicateMethodCall']['max_calls']).to eq 3
|
58
47
|
end
|
59
48
|
|
60
49
|
it 'parses multiple hashed options' do
|
61
50
|
comment = <<-RUBY
|
62
|
-
# :reek:DuplicateMethodCall {
|
51
|
+
# :reek:DuplicateMethodCall { max_calls: 3 }
|
63
52
|
# :reek:NestedIterators { enabled: true }
|
64
53
|
RUBY
|
65
|
-
config =
|
54
|
+
config = build_code_comment(comment: comment).config
|
66
55
|
|
67
56
|
expect(config).to include('DuplicateMethodCall', 'NestedIterators')
|
68
|
-
expect(config['DuplicateMethodCall']).to
|
69
|
-
expect(config['DuplicateMethodCall']['enabled']).to be_falsey
|
70
|
-
expect(config['NestedIterators']).to include('enabled')
|
57
|
+
expect(config['DuplicateMethodCall']['max_calls']).to eq 3
|
71
58
|
expect(config['NestedIterators']['enabled']).to be_truthy
|
72
59
|
end
|
73
60
|
|
74
61
|
it 'parses multiple hashed options on the same line' do
|
75
62
|
comment = <<-RUBY
|
76
|
-
#:reek:DuplicateMethodCall {
|
63
|
+
#:reek:DuplicateMethodCall { max_calls: 3 } and :reek:NestedIterators { enabled: true }
|
77
64
|
RUBY
|
78
|
-
config =
|
65
|
+
config = build_code_comment(comment: comment).config
|
79
66
|
|
80
67
|
expect(config).to include('DuplicateMethodCall', 'NestedIterators')
|
81
|
-
expect(config['DuplicateMethodCall']).to
|
82
|
-
expect(config['DuplicateMethodCall']['enabled']).to be_falsey
|
68
|
+
expect(config['DuplicateMethodCall']['max_calls']).to eq 3
|
83
69
|
expect(config['NestedIterators']).to include('enabled')
|
84
70
|
expect(config['NestedIterators']['enabled']).to be_truthy
|
85
71
|
end
|
86
72
|
|
87
73
|
it 'parses multiple unhashed options on the same line' do
|
88
74
|
comment = '# :reek:DuplicateMethodCall and :reek:NestedIterators'
|
89
|
-
config =
|
75
|
+
config = build_code_comment(comment: comment).config
|
90
76
|
|
91
77
|
expect(config).to include('DuplicateMethodCall', 'NestedIterators')
|
92
78
|
expect(config['DuplicateMethodCall']).to include('enabled')
|
@@ -97,27 +83,33 @@ RSpec.describe Reek::CodeComment do
|
|
97
83
|
|
98
84
|
it 'disables the smell if no options are specifed' do
|
99
85
|
comment = '# :reek:DuplicateMethodCall'
|
100
|
-
config =
|
86
|
+
config = build_code_comment(comment: comment).config
|
101
87
|
|
102
88
|
expect(config).to include('DuplicateMethodCall')
|
103
89
|
expect(config['DuplicateMethodCall']).to include('enabled')
|
104
90
|
expect(config['DuplicateMethodCall']['enabled']).to be_falsey
|
105
91
|
end
|
106
92
|
|
93
|
+
it 'does not disable the smell if options are specifed' do
|
94
|
+
comment = '# :reek:DuplicateMethodCall { max_calls: 3 }'
|
95
|
+
config = build_code_comment(comment: comment).config
|
96
|
+
|
97
|
+
expect(config['DuplicateMethodCall']).not_to include('enabled')
|
98
|
+
end
|
99
|
+
|
107
100
|
it 'ignores smells after a space' do
|
108
|
-
config =
|
109
|
-
comment: '# :reek: DuplicateMethodCall').config
|
101
|
+
config = build_code_comment(comment: '# :reek: DuplicateMethodCall').config
|
110
102
|
expect(config).not_to include('DuplicateMethodCall')
|
111
103
|
end
|
112
104
|
|
113
105
|
it 'removes the configuration options from the comment' do
|
114
106
|
original_comment = <<-RUBY
|
115
107
|
# Actual
|
116
|
-
# :reek:DuplicateMethodCall {
|
108
|
+
# :reek:DuplicateMethodCall { max_calls: 3 }
|
117
109
|
# :reek:NestedIterators { enabled: true }
|
118
110
|
# comment
|
119
111
|
RUBY
|
120
|
-
comment =
|
112
|
+
comment = build_code_comment(comment: original_comment)
|
121
113
|
|
122
114
|
expect(comment.send(:sanitized_comment)).to eq('Actual comment')
|
123
115
|
end
|
@@ -128,8 +120,7 @@ RSpec.describe Reek::CodeComment::CodeCommentValidator do
|
|
128
120
|
context 'when the comment contains an unknown detector name' do
|
129
121
|
it 'raises BadDetectorInCommentError' do
|
130
122
|
expect do
|
131
|
-
|
132
|
-
comment: '# :reek:DoesNotExist')
|
123
|
+
build_code_comment(comment: '# :reek:DoesNotExist')
|
133
124
|
end.to raise_error(Reek::Errors::BadDetectorInCommentError)
|
134
125
|
end
|
135
126
|
end
|
@@ -138,18 +129,26 @@ RSpec.describe Reek::CodeComment::CodeCommentValidator do
|
|
138
129
|
it 'raises GarbageDetectorConfigurationInCommentError' do
|
139
130
|
expect do
|
140
131
|
comment = '# :reek:UncommunicativeMethodName { thats: a: bad: config }'
|
141
|
-
|
132
|
+
build_code_comment(comment: comment)
|
142
133
|
end.to raise_error(Reek::Errors::GarbageDetectorConfigurationInCommentError)
|
143
134
|
end
|
144
135
|
end
|
145
136
|
|
137
|
+
context 'when the legacy comment format was used' do
|
138
|
+
it 'raises LegacyCommentSeparatorError' do
|
139
|
+
comment = '# :reek:DuplicateMethodCall:'
|
140
|
+
expect { build_code_comment(comment: comment) }.
|
141
|
+
to raise_error Reek::Errors::LegacyCommentSeparatorError
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
146
145
|
describe 'validating configuration keys' do
|
147
146
|
context 'when basic options are mispelled' do
|
148
147
|
it 'raises BadDetectorConfigurationKeyInCommentError' do
|
149
148
|
expect do
|
150
149
|
# exclude -> exlude and enabled -> nabled
|
151
150
|
comment = '# :reek:UncommunicativeMethodName { exlude: alfa, nabled: true }'
|
152
|
-
|
151
|
+
build_code_comment(comment: comment)
|
153
152
|
end.to raise_error(Reek::Errors::BadDetectorConfigurationKeyInCommentError)
|
154
153
|
end
|
155
154
|
end
|
@@ -158,7 +157,7 @@ RSpec.describe Reek::CodeComment::CodeCommentValidator do
|
|
158
157
|
it 'does not raise' do
|
159
158
|
expect do
|
160
159
|
comment = '# :reek:UncommunicativeMethodName { exclude: alfa, enabled: true }'
|
161
|
-
|
160
|
+
build_code_comment(comment: comment)
|
162
161
|
end.not_to raise_error
|
163
162
|
end
|
164
163
|
end
|
@@ -168,7 +167,7 @@ RSpec.describe Reek::CodeComment::CodeCommentValidator do
|
|
168
167
|
expect do
|
169
168
|
# max_copies -> mx_copies and min_clump_size -> mn_clump_size
|
170
169
|
comment = '# :reek:DataClump { mx_copies: 4, mn_clump_size: 3 }'
|
171
|
-
|
170
|
+
build_code_comment(comment: comment)
|
172
171
|
end.to raise_error(Reek::Errors::BadDetectorConfigurationKeyInCommentError)
|
173
172
|
end
|
174
173
|
end
|
@@ -177,7 +176,7 @@ RSpec.describe Reek::CodeComment::CodeCommentValidator do
|
|
177
176
|
it 'does not raise' do
|
178
177
|
expect do
|
179
178
|
comment = '# :reek:DataClump { max_copies: 4, min_clump_size: 3 }'
|
180
|
-
|
179
|
+
build_code_comment(comment: comment)
|
181
180
|
end.not_to raise_error
|
182
181
|
end
|
183
182
|
end
|
@@ -89,6 +89,12 @@ RSpec.describe Reek::Configuration::DirectoryDirectives do
|
|
89
89
|
expect(hit.to_s).to eq('bar/**/.spec/*')
|
90
90
|
end
|
91
91
|
|
92
|
+
it 'returns the corresponding directory when source_base_dir is an absolute_path' do
|
93
|
+
source_base_dir = Pathname.new('foo/bar').expand_path
|
94
|
+
hit = directives.send :best_match_for, source_base_dir
|
95
|
+
expect(hit.to_s).to eq('foo/bar')
|
96
|
+
end
|
97
|
+
|
92
98
|
it 'does not match an arbitrary directory when source_base_dir contains a character that could match the .' do
|
93
99
|
source_base_dir = 'bar/something/aspec/direct'
|
94
100
|
hit = directives.send :best_match_for, source_base_dir
|
@@ -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
|