reek 3.2.1 → 3.3.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.
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 }