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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +8 -6
  4. data/.rubocop_todo.yml +25 -20
  5. data/.simplecov +1 -0
  6. data/.travis.yml +17 -11
  7. data/CHANGELOG.md +31 -3
  8. data/Dockerfile +1 -0
  9. data/Gemfile +14 -17
  10. data/README.md +15 -11
  11. data/bin/code_climate_reek +12 -2
  12. data/docs/Attribute.md +1 -1
  13. data/docs/Boolean-Parameter.md +1 -1
  14. data/docs/Control-Couple.md +1 -1
  15. data/docs/Nil-Check.md +4 -1
  16. data/features/command_line_interface/options.feature +2 -3
  17. data/features/configuration_files/schema_validation.feature +1 -1
  18. data/features/reports/codeclimate.feature +2 -2
  19. data/features/reports/json.feature +3 -3
  20. data/features/reports/reports.feature +4 -4
  21. data/features/reports/yaml.feature +3 -3
  22. data/features/step_definitions/reek_steps.rb +5 -1
  23. data/features/step_definitions/sample_file_steps.rb +2 -2
  24. data/features/support/env.rb +1 -2
  25. data/lib/reek.rb +1 -0
  26. data/lib/reek/ast/sexp_extensions/arguments.rb +11 -0
  27. data/lib/reek/cli/options.rb +3 -3
  28. data/lib/reek/code_comment.rb +45 -38
  29. data/lib/reek/configuration/app_configuration.rb +4 -3
  30. data/lib/reek/configuration/configuration_converter.rb +2 -2
  31. data/lib/reek/configuration/directory_directives.rb +9 -3
  32. data/lib/reek/context/module_context.rb +3 -1
  33. data/lib/reek/errors/legacy_comment_separator_error.rb +36 -0
  34. data/lib/reek/examiner.rb +3 -3
  35. data/lib/reek/report.rb +5 -7
  36. data/lib/reek/report/code_climate/code_climate_configuration.yml +1 -1
  37. data/lib/reek/report/code_climate/code_climate_report.rb +2 -1
  38. data/lib/reek/report/simple_warning_formatter.rb +0 -7
  39. data/lib/reek/report/text_report.rb +2 -2
  40. data/lib/reek/smell_detectors/base_detector.rb +1 -9
  41. data/lib/reek/smell_detectors/boolean_parameter.rb +3 -1
  42. data/lib/reek/smell_detectors/data_clump.rb +23 -56
  43. data/lib/reek/smell_detectors/nil_check.rb +1 -12
  44. data/lib/reek/smell_detectors/subclassed_from_core_class.rb +3 -7
  45. data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +1 -1
  46. data/lib/reek/smell_warning.rb +1 -2
  47. data/lib/reek/source/source_code.rb +3 -2
  48. data/lib/reek/source/source_locator.rb +13 -10
  49. data/lib/reek/spec/smell_matcher.rb +2 -1
  50. data/lib/reek/version.rb +1 -1
  51. data/reek.gemspec +13 -6
  52. data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +2 -4
  53. data/spec/quality/documentation_spec.rb +2 -1
  54. data/spec/reek/ast/sexp_extensions_spec.rb +15 -33
  55. data/spec/reek/code_comment_spec.rb +41 -42
  56. data/spec/reek/configuration/directory_directives_spec.rb +6 -0
  57. data/spec/reek/context_builder_spec.rb +110 -113
  58. data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +1 -3
  59. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +26 -26
  60. data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +6 -6
  61. data/spec/reek/report/code_climate/code_climate_report_spec.rb +1 -1
  62. data/spec/reek/report/json_report_spec.rb +1 -1
  63. data/spec/reek/report/location_formatter_spec.rb +3 -3
  64. data/spec/reek/report/text_report_spec.rb +1 -7
  65. data/spec/reek/report/yaml_report_spec.rb +1 -1
  66. data/spec/reek/smell_detectors/base_detector_spec.rb +3 -13
  67. data/spec/reek/smell_detectors/data_clump_spec.rb +14 -0
  68. data/spec/reek/smell_detectors/missing_safe_method_spec.rb +8 -2
  69. data/spec/reek/smell_detectors/nil_check_spec.rb +3 -3
  70. data/spec/reek/smell_warning_spec.rb +12 -12
  71. data/spec/reek/source/source_code_spec.rb +13 -0
  72. data/spec/reek/spec/should_reek_of_spec.rb +0 -1
  73. data/spec/reek/spec/should_reek_only_of_spec.rb +6 -6
  74. data/spec/reek/spec/smell_matcher_spec.rb +1 -1
  75. data/spec/spec_helper.rb +20 -6
  76. data/tasks/configuration.rake +1 -2
  77. metadata +15 -25
  78. 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
- context 'with single assignment' do
447
- it 'does not define a module' do
448
- exp = sexp(:casgn, nil, :Foo)
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
- context 'with implicit receiver to new' do
454
- it 'does not define a module' do
455
- exp = sexp(:casgn, nil, :Foo, sexp(:send, nil, :new))
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
- context 'with implicit receiver to new' do
461
- it 'does not define a module' do
462
- exp = Reek::Source::SourceCode.from('Foo = Class.new(Bar)').syntax_tree
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
- context 'when assigning a lambda to a constant' do
469
- it 'does not define a module' do
470
- exp = Reek::Source::SourceCode.from('C = ->{}').syntax_tree
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
- context 'when assigning a string to a constant' do
477
- it 'does not define a module' do
478
- exp = Reek::Source::SourceCode.from('C = "hello"').syntax_tree
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) { build(:code_comment, 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 = build(:code_comment, 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 = build(:code_comment, comment: "# alpha\n# ")
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 = build(:code_comment, comment: '# alpha bravo ')
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 = build(:code_comment, comment: "# alpha bravo \n# charlie \n # delta ")
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 { enabled: false }'
42
- config = build(:code_comment,
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 include('enabled')
47
- expect(config['DuplicateMethodCall']['enabled']).to be_falsey
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 { enabled: false }
51
+ # :reek:DuplicateMethodCall { max_calls: 3 }
63
52
  # :reek:NestedIterators { enabled: true }
64
53
  RUBY
65
- config = build(:code_comment, comment: comment).config
54
+ config = build_code_comment(comment: comment).config
66
55
 
67
56
  expect(config).to include('DuplicateMethodCall', 'NestedIterators')
68
- expect(config['DuplicateMethodCall']).to include('enabled')
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 { enabled: false } and :reek:NestedIterators { enabled: true }
63
+ #:reek:DuplicateMethodCall { max_calls: 3 } and :reek:NestedIterators { enabled: true }
77
64
  RUBY
78
- config = build(:code_comment, comment: comment).config
65
+ config = build_code_comment(comment: comment).config
79
66
 
80
67
  expect(config).to include('DuplicateMethodCall', 'NestedIterators')
81
- expect(config['DuplicateMethodCall']).to include('enabled')
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 = build(:code_comment, comment: comment).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 = build(:code_comment, comment: comment).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 = build(:code_comment,
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 { enabled: false }
108
+ # :reek:DuplicateMethodCall { max_calls: 3 }
117
109
  # :reek:NestedIterators { enabled: true }
118
110
  # comment
119
111
  RUBY
120
- comment = build(:code_comment, comment: original_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
- build(:code_comment,
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
- build(:code_comment, comment: comment)
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
- build(:code_comment, comment: comment)
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
- build(:code_comment, comment: comment)
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
- build(:code_comment, comment: comment)
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
- build(:code_comment, comment: comment)
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
- let(:walker) do
7
- code = 'class Car; def drive; end; end'
8
- described_class.new(syntax_tree(code))
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 'starts with a root node' do
15
- expect(context_tree.type).to eq(:root)
16
- expect(context_tree).to be_a(Reek::Context::RootContext)
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 'has one child' do
20
- expect(context_tree.children.size).to eq(1)
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
- describe 'the root node' do
24
- it 'has one module_context' do
25
- expect(module_context).to be_a(Reek::Context::ModuleContext)
26
- end
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
- it 'holds a reference to the parent context' do
29
- expect(module_context.parent).to eq(context_tree)
30
- end
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
- describe 'the module node' do
34
- it 'has one method_context' do
35
- expect(method_context).to be_a(Reek::Context::MethodContext)
36
- expect(module_context.children.size).to eq(1)
37
- end
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
- it 'holds a reference to the parent context' do
40
- expect(method_context.parent).to eq(module_context)
41
- end
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