reek 3.2.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/Rakefile +0 -1
  4. data/config/defaults.reek +1 -1
  5. data/features/samples.feature +17 -16
  6. data/lib/reek.rb +0 -1
  7. data/lib/reek/ast/ast_node_class_map.rb +5 -1
  8. data/lib/reek/ast/node.rb +10 -3
  9. data/lib/reek/ast/object_refs.rb +11 -5
  10. data/lib/reek/ast/reference_collector.rb +6 -2
  11. data/lib/reek/ast/sexp_extensions.rb +42 -1
  12. data/lib/reek/ast/sexp_formatter.rb +2 -1
  13. data/lib/reek/cli/application.rb +12 -9
  14. data/lib/reek/cli/command.rb +6 -0
  15. data/lib/reek/cli/input.rb +4 -4
  16. data/lib/reek/cli/option_interpreter.rb +11 -7
  17. data/lib/reek/cli/options.rb +42 -40
  18. data/lib/reek/cli/reek_command.rb +3 -3
  19. data/lib/reek/cli/silencer.rb +12 -3
  20. data/lib/reek/cli/warning_collector.rb +8 -3
  21. data/lib/reek/code_comment.rb +6 -1
  22. data/lib/reek/configuration/app_configuration.rb +65 -100
  23. data/lib/reek/configuration/configuration_file_finder.rb +4 -13
  24. data/lib/reek/configuration/configuration_validator.rb +35 -0
  25. data/lib/reek/configuration/default_directive.rb +12 -0
  26. data/lib/reek/configuration/directory_directives.rb +54 -0
  27. data/lib/reek/configuration/excluded_paths.rb +18 -0
  28. data/lib/reek/context/code_context.rb +19 -17
  29. data/lib/reek/examiner.rb +9 -7
  30. data/lib/reek/rake/task.rb +12 -22
  31. data/lib/reek/report/formatter.rb +6 -1
  32. data/lib/reek/report/report.rb +22 -13
  33. data/lib/reek/smells/attribute.rb +6 -53
  34. data/lib/reek/smells/control_parameter.rb +21 -13
  35. data/lib/reek/smells/data_clump.rb +17 -9
  36. data/lib/reek/smells/duplicate_method_call.rb +12 -6
  37. data/lib/reek/smells/long_parameter_list.rb +2 -2
  38. data/lib/reek/smells/long_yield_list.rb +4 -4
  39. data/lib/reek/smells/nested_iterators.rb +4 -2
  40. data/lib/reek/smells/nil_check.rb +6 -2
  41. data/lib/reek/smells/repeated_conditional.rb +3 -3
  42. data/lib/reek/smells/smell_configuration.rb +17 -7
  43. data/lib/reek/smells/smell_detector.rb +24 -11
  44. data/lib/reek/smells/smell_repository.rb +1 -1
  45. data/lib/reek/smells/smell_warning.rb +6 -6
  46. data/lib/reek/smells/too_many_instance_variables.rb +2 -2
  47. data/lib/reek/smells/too_many_methods.rb +4 -4
  48. data/lib/reek/smells/too_many_statements.rb +4 -4
  49. data/lib/reek/smells/uncommunicative_method_name.rb +5 -5
  50. data/lib/reek/smells/uncommunicative_module_name.rb +6 -6
  51. data/lib/reek/smells/uncommunicative_parameter_name.rb +8 -4
  52. data/lib/reek/smells/uncommunicative_variable_name.rb +9 -5
  53. data/lib/reek/smells/utility_function.rb +1 -1
  54. data/lib/reek/source/source_code.rb +5 -1
  55. data/lib/reek/source/source_locator.rb +3 -2
  56. data/lib/reek/spec.rb +3 -3
  57. data/lib/reek/spec/should_reek.rb +10 -5
  58. data/lib/reek/spec/should_reek_of.rb +9 -6
  59. data/lib/reek/spec/should_reek_only_of.rb +13 -8
  60. data/lib/reek/tree_dresser.rb +6 -2
  61. data/lib/reek/tree_walker.rb +40 -32
  62. data/lib/reek/version.rb +1 -1
  63. data/reek.gemspec +1 -1
  64. data/spec/reek/ast/node_spec.rb +1 -2
  65. data/spec/reek/ast/object_refs_spec.rb +40 -42
  66. data/spec/reek/ast/sexp_extensions_spec.rb +98 -104
  67. data/spec/reek/cli/warning_collector_spec.rb +8 -12
  68. data/spec/reek/code_comment_spec.rb +3 -5
  69. data/spec/reek/configuration/app_configuration_spec.rb +43 -57
  70. data/spec/reek/configuration/configuration_file_finder_spec.rb +5 -7
  71. data/spec/reek/configuration/default_directive_spec.rb +13 -0
  72. data/spec/reek/configuration/directory_directives_spec.rb +89 -0
  73. data/spec/reek/configuration/excluded_paths_spec.rb +30 -0
  74. data/spec/reek/context/code_context_spec.rb +63 -62
  75. data/spec/reek/context/method_context_spec.rb +8 -12
  76. data/spec/reek/context/module_context_spec.rb +1 -1
  77. data/spec/reek/context/root_context_spec.rb +3 -7
  78. data/spec/reek/examiner_spec.rb +14 -25
  79. data/spec/reek/smells/attribute_spec.rb +2 -4
  80. data/spec/reek/smells/boolean_parameter_spec.rb +5 -7
  81. data/spec/reek/smells/class_variable_spec.rb +29 -44
  82. data/spec/reek/smells/control_parameter_spec.rb +7 -9
  83. data/spec/reek/smells/data_clump_spec.rb +25 -32
  84. data/spec/reek/smells/duplicate_method_call_spec.rb +8 -7
  85. data/spec/reek/smells/feature_envy_spec.rb +16 -17
  86. data/spec/reek/smells/irresponsible_module_spec.rb +2 -4
  87. data/spec/reek/smells/long_parameter_list_spec.rb +6 -9
  88. data/spec/reek/smells/long_yield_list_spec.rb +6 -9
  89. data/spec/reek/smells/nested_iterators_spec.rb +14 -16
  90. data/spec/reek/smells/repeated_conditional_spec.rb +25 -25
  91. data/spec/reek/smells/smell_configuration_spec.rb +32 -27
  92. data/spec/reek/smells/smell_detector_shared.rb +12 -13
  93. data/spec/reek/smells/smell_warning_spec.rb +54 -58
  94. data/spec/reek/smells/too_many_instance_variables_spec.rb +9 -9
  95. data/spec/reek/smells/too_many_methods_spec.rb +13 -14
  96. data/spec/reek/smells/too_many_statements_spec.rb +8 -10
  97. data/spec/reek/smells/uncommunicative_method_name_spec.rb +8 -9
  98. data/spec/reek/smells/uncommunicative_module_name_spec.rb +12 -13
  99. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +7 -10
  100. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +16 -20
  101. data/spec/reek/smells/utility_function_spec.rb +11 -15
  102. data/spec/reek/source/source_code_spec.rb +6 -11
  103. data/spec/reek/spec/should_reek_of_spec.rb +19 -30
  104. data/spec/reek/spec/should_reek_only_of_spec.rb +28 -34
  105. data/spec/reek/tree_walker_spec.rb +14 -2
  106. data/spec/spec_helper.rb +2 -3
  107. data/tasks/test.rake +0 -5
  108. metadata +10 -6
  109. data/docs/Configuration-Files.md +0 -49
  110. data/spec/gem/updates_spec.rb +0 -25
  111. data/spec/gem/yard_spec.rb +0 -11
  112. data/spec/reek/smells/behaves_like_variable_detector.rb +0 -39
@@ -3,26 +3,22 @@ require_relative '../../../lib/reek/cli/warning_collector'
3
3
  require_relative '../../../lib/reek/smells/smell_warning'
4
4
 
5
5
  RSpec.describe Reek::CLI::WarningCollector do
6
- before(:each) do
7
- @collector = described_class.new
8
- end
6
+ let(:collector) { described_class.new }
9
7
 
10
8
  context 'when empty' do
11
9
  it 'reports no warnings' do
12
- expect(@collector.warnings).to eq([])
10
+ expect(collector.warnings).to eq([])
13
11
  end
14
12
  end
15
13
 
16
14
  context 'with one warning' do
17
- before :each do
18
- @warning = Reek::Smells::SmellWarning.new(Reek::Smells::FeatureEnvy.new(''),
19
- context: 'fred',
20
- lines: [1, 2, 3],
21
- message: 'hello')
22
- @collector.found_smell(@warning)
23
- end
24
15
  it 'reports that warning' do
25
- expect(@collector.warnings).to eq([@warning])
16
+ warning = Reek::Smells::SmellWarning.new(Reek::Smells::FeatureEnvy.new(''),
17
+ context: 'fred',
18
+ lines: [1, 2, 3],
19
+ message: 'hello')
20
+ collector.found_smell(warning)
21
+ expect(collector.warnings).to eq([warning])
26
22
  end
27
23
  end
28
24
  end
@@ -3,14 +3,12 @@ require_relative '../../lib/reek/code_comment'
3
3
 
4
4
  RSpec.describe Reek::CodeComment do
5
5
  context 'with an empty comment' do
6
- before :each do
7
- @comment = described_class.new('')
8
- end
6
+ let(:comment) { described_class.new('') }
9
7
  it 'is not descriptive' do
10
- expect(@comment).not_to be_descriptive
8
+ expect(comment).not_to be_descriptive
11
9
  end
12
10
  it 'has an empty config' do
13
- expect(@comment.config).to be_empty
11
+ expect(comment.config).to be_empty
14
12
  end
15
13
  end
16
14
 
@@ -1,13 +1,19 @@
1
1
  require 'pathname'
2
2
  require_relative '../../spec_helper'
3
3
  require_relative '../../../lib/reek/configuration/app_configuration'
4
- require_relative '../../../lib/reek/smells/smell_repository'
5
- require_relative '../../../lib/reek/source/source_code'
4
+ require_relative '../../../lib/reek/configuration/directory_directives'
5
+ require_relative '../../../lib/reek/configuration/default_directive'
6
+ require_relative '../../../lib/reek/configuration/excluded_paths'
6
7
 
7
8
  RSpec.describe Reek::Configuration::AppConfiguration do
8
- describe '#initialize' do
9
- let(:full_configuration_path) { SAMPLES_PATH.join('configuration/full_configuration.reek') }
10
- let(:expected_exclude_paths) do
9
+ describe '#new' do
10
+ it 'raises NotImplementedError' do
11
+ expect { subject }.to raise_error(NotImplementedError)
12
+ end
13
+ end
14
+
15
+ describe 'factory methods' do
16
+ let(:expected_excluded_paths) do
11
17
  [SAMPLES_PATH.join('two_smelly_files'),
12
18
  SAMPLES_PATH.join('source_with_non_ruby_files')]
13
19
  end
@@ -19,13 +25,28 @@ RSpec.describe Reek::Configuration::AppConfiguration do
19
25
  { Reek::Smells::UtilityFunction => { 'enabled' => false } } }
20
26
  end
21
27
 
22
- it 'properly loads configuration and processes it' do
23
- finder = Reek::Configuration::ConfigurationFileFinder
24
- allow(finder).to receive(:find_by_cli).and_return full_configuration_path
28
+ describe '#from_path' do
29
+ let(:full_configuration_path) { SAMPLES_PATH.join('configuration/full_configuration.reek') }
30
+
31
+ it 'properly loads configuration and processes it' do
32
+ config = described_class.from_path full_configuration_path
33
+
34
+ expect(config.send(:excluded_paths)).to eq(expected_excluded_paths)
35
+ expect(config.send(:default_directive)).to eq(expected_default_directive)
36
+ expect(config.send(:directory_directives)).to eq(expected_directory_directives)
37
+ end
38
+ end
39
+
40
+ describe '#from_map' do
41
+ it 'properly sets the configuration' do
42
+ config = described_class.from_map(directory_directives: expected_directory_directives,
43
+ default_directive: expected_default_directive,
44
+ excluded_paths: expected_excluded_paths)
25
45
 
26
- expect(subject.exclude_paths).to eq(expected_exclude_paths)
27
- expect(subject.default_directive).to eq(expected_default_directive)
28
- expect(subject.directory_directives).to eq(expected_directory_directives)
46
+ expect(config.send(:excluded_paths)).to eq(expected_excluded_paths)
47
+ expect(config.send(:default_directive)).to eq(expected_default_directive)
48
+ expect(config.send(:directory_directives)).to eq(expected_directory_directives)
49
+ end
29
50
  end
30
51
  end
31
52
 
@@ -43,64 +64,29 @@ RSpec.describe Reek::Configuration::AppConfiguration do
43
64
  let(:source_via) { 'foo/bar/bang/dummy.rb' }
44
65
 
45
66
  it 'returns the corresponding directive' do
46
- allow(subject).to receive(:directory_directives).and_return directory_directives
47
- expect(subject.directive_for(source_via)).to eq(bang_config)
67
+ configuration = described_class.from_map directory_directives: directory_directives
68
+ expect(configuration.directive_for(source_via)).to eq(bang_config)
48
69
  end
49
70
  end
50
71
 
51
72
  context 'our source is not in a directory for which we have a directive' do
52
- let(:baz_config) { { Reek::Smells::IrresponsibleModule => { enabled: false } } }
73
+ let(:irresponsible_module_config) do
74
+ { Reek::Smells::IrresponsibleModule => { enabled: false } }
75
+ end
76
+ let(:attribute_config) { { Reek::Smells::Attribute => { enabled: false } } }
53
77
  let(:default_directive) do
54
- { Reek::Smells::Attribute => { enabled: true } }
78
+ irresponsible_module_config
55
79
  end
56
80
  let(:directory_directives) do
57
- { Pathname.new('foo/bar/baz') => baz_config }
81
+ { Pathname.new('foo/bar/baz') => attribute_config }
58
82
  end
59
83
  let(:source_via) { 'foo/bar/bang/dummy.rb' }
60
84
 
61
85
  it 'returns the default directive' do
62
- allow(subject).to receive(:directory_directives).and_return directory_directives
63
- allow(subject).to receive(:default_directive).and_return default_directive
64
- expect(subject.directive_for(source_via)).to eq(default_directive)
86
+ configuration = described_class.from_map directory_directives: directory_directives,
87
+ default_directive: default_directive
88
+ expect(configuration.directive_for(source_via)).to eq(irresponsible_module_config)
65
89
  end
66
90
  end
67
91
  end
68
-
69
- describe '#best_directory_match_for' do
70
- let(:directory_directives) do
71
- {
72
- Pathname.new('foo/bar/baz') => {},
73
- Pathname.new('foo/bar') => {},
74
- Pathname.new('bar/boo') => {}
75
- }
76
- end
77
-
78
- before do
79
- allow(subject).to receive(:directory_directives).and_return directory_directives
80
- end
81
-
82
- it 'returns the corresponding directory when source_base_dir is a leaf' do
83
- source_base_dir = 'foo/bar/baz/bang'
84
- hit = subject.send :best_directory_match_for, source_base_dir
85
- expect(hit.to_s).to eq('foo/bar/baz')
86
- end
87
-
88
- it 'returns the corresponding directory when source_base_dir is in the middle of the tree' do
89
- source_base_dir = 'foo/bar'
90
- hit = subject.send :best_directory_match_for, source_base_dir
91
- expect(hit.to_s).to eq('foo/bar')
92
- end
93
-
94
- it 'returns nil we are on top at the top of the and all other directories are below' do
95
- source_base_dir = 'foo'
96
- hit = subject.send :best_directory_match_for, source_base_dir
97
- expect(hit).to be_nil
98
- end
99
-
100
- it 'returns nil when there source_base_dir is not part of any directory directive at all' do
101
- source_base_dir = 'non/existent'
102
- hit = subject.send :best_directory_match_for, source_base_dir
103
- expect(hit).to be_nil
104
- end
105
- end
106
92
  end
@@ -7,16 +7,14 @@ require_relative '../../spec_helper'
7
7
 
8
8
  RSpec.describe Reek::Configuration::ConfigurationFileFinder do
9
9
  describe '.find' do
10
- it 'returns the config_file if it’s set' do
11
- config_file = double
12
- options = double(config_file: config_file)
13
- found = described_class.find(options: options)
14
- expect(found).to eq(config_file)
10
+ it 'returns the path if it’s set' do
11
+ path = Pathname.new 'foo/bar'
12
+ found = described_class.find(path: path)
13
+ expect(found).to eq(path)
15
14
  end
16
15
 
17
16
  it 'returns the file in current dir if config_file is nil' do
18
- options = double(config_file: nil)
19
- found = described_class.find(options: options, current: SAMPLES_PATH)
17
+ found = described_class.find(current: SAMPLES_PATH)
20
18
  expect(found).to eq(SAMPLES_PATH.join('exceptions.reek'))
21
19
  end
22
20
 
@@ -0,0 +1,13 @@
1
+ require_relative '../../spec_helper'
2
+ require_relative '../../../lib/reek/configuration/default_directive'
3
+
4
+ RSpec.describe Reek::Configuration::DefaultDirective do
5
+ describe '#add' do
6
+ subject { {}.extend(described_class) }
7
+
8
+ it 'adds a smell configuration' do
9
+ subject.add :UncommunicativeVariableName, enabled: false
10
+ expect(subject).to eq(Reek::Smells::UncommunicativeVariableName => { enabled: false })
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,89 @@
1
+ require_relative '../../spec_helper'
2
+ require_relative '../../../lib/reek/configuration/directory_directives'
3
+
4
+ RSpec.describe Reek::Configuration::DirectoryDirectives do
5
+ describe '#directive_for' do
6
+ let(:baz_config) { { Reek::Smells::IrresponsibleModule => { enabled: false } } }
7
+ let(:bang_config) { { Reek::Smells::Attribute => { enabled: true } } }
8
+ subject do
9
+ {
10
+ Pathname.new('foo/bar/baz') => baz_config,
11
+ Pathname.new('foo/bar/bang') => bang_config
12
+ }.extend(described_class)
13
+ end
14
+ let(:source_via) { 'foo/bar/bang/dummy.rb' }
15
+
16
+ context 'our source is in a directory for which we have a directive' do
17
+ it 'returns the corresponding directive' do
18
+ expect(subject.directive_for(source_via)).to eq(bang_config)
19
+ end
20
+ end
21
+
22
+ context 'our source is not in a directory for which we have a directive' do
23
+ it 'returns nil' do
24
+ expect(subject.directive_for('does/not/exist')).to eq(nil)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '#add' do
30
+ subject do
31
+ {}.extend(described_class)
32
+ end
33
+ let(:empty_config) { Hash.new }
34
+
35
+ context 'one of given paths does not exist' do
36
+ let(:bogus_path) { Pathname('does/not/exist') }
37
+
38
+ it 'raises an error' do
39
+ Reek::CLI::Silencer.silently(stderr: true) do
40
+ expect { subject.add(bogus_path, {}) }.to raise_error(SystemExit)
41
+ end
42
+ end
43
+ end
44
+
45
+ context 'one of given paths is a file' do
46
+ let(:file_as_path) { SAMPLES_PATH.join('inline.rb') }
47
+
48
+ it 'raises an error' do
49
+ Reek::CLI::Silencer.silently(stderr: true) do
50
+ expect { subject.add(file_as_path, {}) }.to raise_error(SystemExit)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ describe '#best_match_for' do
57
+ subject do
58
+ {
59
+ Pathname.new('foo/bar/baz') => {},
60
+ Pathname.new('foo/bar') => {},
61
+ Pathname.new('bar/boo') => {}
62
+ }.extend(described_class)
63
+ end
64
+
65
+ it 'returns the corresponding directory when source_base_dir is a leaf' do
66
+ source_base_dir = 'foo/bar/baz/bang'
67
+ hit = subject.send :best_match_for, source_base_dir
68
+ expect(hit.to_s).to eq('foo/bar/baz')
69
+ end
70
+
71
+ it 'returns the corresponding directory when source_base_dir is in the middle of the tree' do
72
+ source_base_dir = 'foo/bar'
73
+ hit = subject.send :best_match_for, source_base_dir
74
+ expect(hit.to_s).to eq('foo/bar')
75
+ end
76
+
77
+ it 'returns nil we are on top of the tree and all other directories are below' do
78
+ source_base_dir = 'foo'
79
+ hit = subject.send :best_match_for, source_base_dir
80
+ expect(hit).to be_nil
81
+ end
82
+
83
+ it 'returns nil when source_base_dir is not part of any directory directive at all' do
84
+ source_base_dir = 'non/existent'
85
+ hit = subject.send :best_match_for, source_base_dir
86
+ expect(hit).to be_nil
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,30 @@
1
+ require_relative '../../spec_helper'
2
+ require_relative '../../../lib/reek/configuration/excluded_paths'
3
+
4
+ RSpec.describe Reek::Configuration::ExcludedPaths do
5
+ describe '#add' do
6
+ subject { [].extend(described_class) }
7
+
8
+ context 'one of the given paths does not exist' do
9
+ let(:bogus_path) { Pathname('does/not/exist') }
10
+ let(:paths) { [SAMPLES_PATH, bogus_path] }
11
+
12
+ it 'raises an error' do
13
+ Reek::CLI::Silencer.silently(stderr: true) do
14
+ expect { subject.add(paths) }.to raise_error(SystemExit)
15
+ end
16
+ end
17
+ end
18
+
19
+ context 'one of given paths is a file' do
20
+ let(:file_as_path) { SAMPLES_PATH.join('inline.rb') }
21
+ let(:paths) { [SAMPLES_PATH, file_as_path] }
22
+
23
+ it 'raises an error if one of the given paths is a file' do
24
+ Reek::CLI::Silencer.silently(stderr: true) do
25
+ expect { subject.add(paths) }.to raise_error(SystemExit)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,107 +4,109 @@ require_relative '../../../lib/reek/context/module_context'
4
4
 
5
5
  RSpec.describe Reek::Context::CodeContext do
6
6
  context 'name recognition' do
7
+ let(:ctx) { Reek::Context::CodeContext.new(nil, exp) }
8
+ let(:exp) { double('exp') }
9
+ let(:exp_name) { 'random_name' }
10
+ let(:full_name) { "::::::::::::::::::::#{exp_name}" }
11
+
7
12
  before :each do
8
- @exp_name = 'random_name' # SMELL: could use a String.random here
9
- @full_name = "::::::::::::::::::::#{@exp_name}"
10
- @exp = double('exp')
11
- allow(@exp).to receive(:name).and_return(@exp_name)
12
- allow(@exp).to receive(:full_name).and_return(@full_name)
13
- @ctx = Reek::Context::CodeContext.new(nil, @exp)
13
+ allow(exp).to receive(:name).and_return(exp_name)
14
+ allow(exp).to receive(:full_name).and_return(full_name)
14
15
  end
16
+
15
17
  it 'gets its short name from the exp' do
16
- expect(@ctx.name).to eq(@exp_name)
18
+ expect(ctx.name).to eq(exp_name)
17
19
  end
18
20
  it 'does not match an empty list' do
19
- expect(@ctx.matches?([])).to eq(false)
21
+ expect(ctx.matches?([])).to eq(false)
20
22
  end
21
23
  it 'does not match when its own short name is not given' do
22
- expect(@ctx.matches?(['banana'])).to eq(false)
24
+ expect(ctx.matches?(['banana'])).to eq(false)
23
25
  end
24
26
  it 'does not let pipe-ended Strings make matching ignore the rest' do
25
- expect(@ctx.matches?(['banana|'])).to eq(false)
27
+ expect(ctx.matches?(['banana|'])).to eq(false)
26
28
  end
27
29
  it 'recognises its own short name' do
28
- expect(@ctx.matches?(['banana', @exp_name])).to eq(true)
30
+ expect(ctx.matches?(['banana', exp_name])).to eq(true)
29
31
  end
30
32
  it 'recognises its short name as a regex' do
31
- expect(@ctx.matches?([/banana/, /#{@exp_name}/])).to eq(true)
33
+ expect(ctx.matches?([/banana/, /#{exp_name}/])).to eq(true)
32
34
  end
33
35
  it 'does not blow up on []-ended Strings' do
34
- expect(@ctx.matches?(['banana[]', @exp_name])).to eq(true)
36
+ expect(ctx.matches?(['banana[]', exp_name])).to eq(true)
35
37
  end
36
38
 
37
39
  context 'when there is an outer' do
38
- let(:outer) { double('outer') }
40
+ let(:ctx) { Reek::Context::CodeContext.new(outer, exp) }
41
+ let(:outer_name) { 'another_random sting' }
42
+ let(:outer) { double('outer') }
43
+
39
44
  before :each do
40
- @outer_name = 'another_random sting'
41
- allow(outer).to receive(:full_name).at_least(:once).and_return(@outer_name)
45
+ allow(outer).to receive(:full_name).at_least(:once).and_return(outer_name)
42
46
  allow(outer).to receive(:config).and_return({})
43
- @ctx = Reek::Context::CodeContext.new(outer, @exp)
44
47
  end
48
+
45
49
  it 'creates the correct full name' do
46
- expect(@ctx.full_name).to eq("#{@full_name}")
50
+ expect(ctx.full_name).to eq(full_name)
47
51
  end
48
52
  it 'recognises its own full name' do
49
- expect(@ctx.matches?(['banana', @full_name])).to eq(true)
53
+ expect(ctx.matches?(['banana', full_name])).to eq(true)
50
54
  end
51
55
  it 'recognises its full name as a regex' do
52
- expect(@ctx.matches?([/banana/, /#{@full_name}/])).to eq(true)
56
+ expect(ctx.matches?([/banana/, /#{full_name}/])).to eq(true)
53
57
  end
54
58
  end
55
59
  end
56
60
 
57
61
  context 'enumerating syntax elements' do
58
62
  context 'in an empty module' do
59
- before :each do
60
- @module_name = 'Emptiness'
61
- src = "module #{@module_name}; end"
63
+ let(:ctx) do
64
+ src = 'module Emptiness; end'
62
65
  ast = Reek::Source::SourceCode.from(src).syntax_tree
63
- @ctx = Reek::Context::CodeContext.new(nil, ast)
66
+ Reek::Context::CodeContext.new(nil, ast)
64
67
  end
65
68
 
66
69
  it 'yields no calls' do
67
- @ctx.each_node(:send, []) { |exp| raise "#{exp} yielded by empty module!" }
70
+ ctx.each_node(:send, []) { |exp| raise "#{exp} yielded by empty module!" }
68
71
  end
69
72
 
70
73
  it 'yields one module' do
71
74
  mods = 0
72
- @ctx.each_node(:module, []) { |_exp| mods += 1 }
75
+ ctx.each_node(:module, []) { |_exp| mods += 1 }
73
76
  expect(mods).to eq(1)
74
77
  end
75
78
 
76
79
  it "yields the module's full AST" do
77
- @ctx.each_node(:module, []) do |exp|
78
- expect(exp).to eq(s(:module, s(:const, nil, @module_name.to_sym), nil))
80
+ ctx.each_node(:module, []) do |exp|
81
+ expect(exp).to eq(s(:module, s(:const, nil, :Emptiness), nil))
79
82
  end
80
83
  end
81
84
 
82
85
  context 'with no block' do
83
86
  it 'returns an empty array of ifs' do
84
- expect(@ctx.each_node(:if, [])).to be_empty
87
+ expect(ctx.each_node(:if, [])).to be_empty
85
88
  end
86
89
  end
87
90
  end
88
91
 
89
92
  context 'with a nested element' do
90
- before :each do
91
- @module_name = 'Loneliness'
92
- @method_name = 'calloo'
93
- src = "module #{@module_name}; def #{@method_name}; puts('hello') end; end"
93
+ let(:ctx) do
94
+ src = "module Loneliness; def calloo; puts('hello') end; end"
94
95
  ast = Reek::Source::SourceCode.from(src).syntax_tree
95
- @ctx = Reek::Context::CodeContext.new(nil, ast)
96
+ Reek::Context::CodeContext.new(nil, ast)
96
97
  end
98
+
97
99
  it 'yields no ifs' do
98
- @ctx.each_node(:if, []) { |exp| raise "#{exp} yielded by empty module!" }
100
+ ctx.each_node(:if, []) { |exp| raise "#{exp} yielded by empty module!" }
99
101
  end
100
102
  it 'yields one module' do
101
- expect(@ctx.each_node(:module, []).length).to eq(1)
103
+ expect(ctx.each_node(:module, []).length).to eq(1)
102
104
  end
103
105
 
104
106
  it "yields the module's full AST" do
105
- @ctx.each_node(:module, []) do |exp|
107
+ ctx.each_node(:module, []) do |exp|
106
108
  expect(exp).to eq s(:module,
107
- s(:const, nil, @module_name.to_sym),
109
+ s(:const, nil, :Loneliness),
108
110
  s(:def, :calloo,
109
111
  s(:args),
110
112
  s(:send, nil, :puts, s(:str, 'hello'))))
@@ -112,37 +114,36 @@ RSpec.describe Reek::Context::CodeContext do
112
114
  end
113
115
 
114
116
  it 'yields one method' do
115
- expect(@ctx.each_node(:def, []).length).to eq(1)
117
+ expect(ctx.each_node(:def, []).length).to eq(1)
116
118
  end
117
119
 
118
120
  it "yields the method's full AST" do
119
- @ctx.each_node(:def, []) { |exp| expect(exp[1]).to eq(@method_name.to_sym) }
121
+ ctx.each_node(:def, []) { |exp| expect(exp[1]).to eq(:calloo) }
120
122
  end
121
123
 
122
124
  context 'pruning the traversal' do
123
125
  it 'ignores the call inside the method' do
124
- expect(@ctx.each_node(:send, [:def])).to be_empty
126
+ expect(ctx.each_node(:send, [:def])).to be_empty
125
127
  end
126
128
  end
127
129
  end
128
130
 
129
131
  it 'finds 3 ifs in a class' do
130
- src = <<EOS
131
- class Scrunch
132
- def first
133
- return @field == :sym ? 0 : 3;
134
- end
135
- def second
136
- if @field == :sym
137
- @other += " quarts"
138
- end
139
- end
140
- def third
141
- raise 'flu!' unless @field == :sym
142
- end
143
- end
144
- EOS
145
-
132
+ src = <<-EOS
133
+ class Scrunch
134
+ def first
135
+ return @field == :sym ? 0 : 3;
136
+ end
137
+ def second
138
+ if @field == :sym
139
+ @other += " quarts"
140
+ end
141
+ end
142
+ def third
143
+ raise 'flu!' unless @field == :sym
144
+ end
145
+ end
146
+ EOS
146
147
  ast = Reek::Source::SourceCode.from(src).syntax_tree
147
148
  ctx = Reek::Context::CodeContext.new(nil, ast)
148
149
  expect(ctx.each_node(:if, []).length).to eq(3)
@@ -152,11 +153,11 @@ EOS
152
153
  describe '#config_for' do
153
154
  let(:src) do
154
155
  <<-EOS
155
- # :reek:DuplicateMethodCall: { allow_calls: [ puts ] }')
156
- def repeated_greeting
157
- puts 'Hello!'
158
- puts 'Hello!'
159
- end
156
+ # :reek:DuplicateMethodCall: { allow_calls: [ puts ] }')
157
+ def repeated_greeting
158
+ puts 'Hello!'
159
+ puts 'Hello!'
160
+ end
160
161
  EOS
161
162
  end
162
163
  let(:expression) { Reek::Source::SourceCode.from(src).syntax_tree }