reek 3.0.4 → 3.1
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/CHANGELOG +6 -0
- data/README.md +41 -20
- data/features/configuration_files/directory_specific_directives.feature +280 -0
- data/features/configuration_files/masking_smells.feature +0 -14
- data/features/step_definitions/sample_file_steps.rb +2 -2
- data/lib/reek/ast/sexp_extensions.rb +72 -60
- data/lib/reek/cli/application.rb +2 -5
- data/lib/reek/cli/reek_command.rb +1 -1
- data/lib/reek/configuration/app_configuration.rb +115 -61
- data/lib/reek/configuration/configuration_file_finder.rb +19 -0
- data/lib/reek/context/code_context.rb +102 -29
- data/lib/reek/context/method_context.rb +11 -48
- data/lib/reek/context/module_context.rb +2 -6
- data/lib/reek/context/root_context.rb +7 -14
- data/lib/reek/examiner.rb +15 -10
- data/lib/reek/report/report.rb +5 -4
- data/lib/reek/smells/boolean_parameter.rb +1 -1
- data/lib/reek/smells/duplicate_method_call.rb +1 -5
- data/lib/reek/smells/irresponsible_module.rb +2 -2
- data/lib/reek/smells/smell_repository.rb +30 -16
- data/lib/reek/smells/utility_function.rb +1 -1
- data/lib/reek/source/source_code.rb +10 -6
- data/lib/reek/source/source_locator.rb +27 -26
- data/lib/reek/spec.rb +8 -6
- data/lib/reek/spec/should_reek.rb +6 -2
- data/lib/reek/spec/should_reek_of.rb +5 -2
- data/lib/reek/spec/should_reek_only_of.rb +1 -1
- data/lib/reek/tree_walker.rb +49 -21
- data/lib/reek/version.rb +1 -1
- data/spec/reek/ast/sexp_extensions_spec.rb +4 -12
- data/spec/reek/configuration/app_configuration_spec.rb +80 -52
- data/spec/reek/configuration/configuration_file_finder_spec.rb +27 -15
- data/spec/reek/context/code_context_spec.rb +66 -17
- data/spec/reek/context/method_context_spec.rb +66 -64
- data/spec/reek/context/root_context_spec.rb +3 -1
- data/spec/reek/context/singleton_method_context_spec.rb +1 -2
- data/spec/reek/examiner_spec.rb +5 -8
- data/spec/reek/report/xml_report_spec.rb +3 -2
- data/spec/reek/smells/attribute_spec.rb +12 -17
- data/spec/reek/smells/duplicate_method_call_spec.rb +17 -25
- data/spec/reek/smells/feature_envy_spec.rb +4 -5
- data/spec/reek/smells/irresponsible_module_spec.rb +43 -0
- data/spec/reek/smells/nested_iterators_spec.rb +12 -26
- data/spec/reek/smells/too_many_statements_spec.rb +2 -210
- data/spec/reek/smells/utility_function_spec.rb +49 -5
- data/spec/reek/source/source_locator_spec.rb +39 -43
- data/spec/reek/spec/should_reek_of_spec.rb +3 -2
- data/spec/reek/spec/should_reek_spec.rb +25 -17
- data/spec/reek/tree_walker_spec.rb +214 -23
- data/spec/samples/configuration/full_configuration.reek +9 -0
- data/spec/spec_helper.rb +10 -10
- metadata +4 -3
- data/features/configuration_files/overrides_defaults.feature +0 -15
@@ -1,11 +1,12 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
2
|
require_relative '../../../lib/reek/smells/utility_function'
|
3
|
+
require_relative '../../../lib/reek/examiner'
|
3
4
|
require_relative 'smell_detector_shared'
|
4
5
|
|
5
6
|
RSpec.describe Reek::Smells::UtilityFunction do
|
6
7
|
describe 'a detector' do
|
7
8
|
before(:each) do
|
8
|
-
@source_name = '
|
9
|
+
@source_name = 'string'
|
9
10
|
@detector = build(:smell_detector,
|
10
11
|
smell_type: :UtilityFunction,
|
11
12
|
source: @source_name)
|
@@ -20,9 +21,7 @@ RSpec.describe Reek::Smells::UtilityFunction do
|
|
20
21
|
arga.b.c
|
21
22
|
end
|
22
23
|
EOS
|
23
|
-
|
24
|
-
mctx = Reek::TreeWalker.new.process_def(source.syntax_tree)
|
25
|
-
@warning = @detector.examine_context(mctx)[0] # SMELL: too cumbersome!
|
24
|
+
@warning = Reek::Examiner.new(src, ['UtilityFunction']).smells[0]
|
26
25
|
end
|
27
26
|
|
28
27
|
it_should_behave_like 'common fields set correctly'
|
@@ -74,11 +73,56 @@ RSpec.describe Reek::Smells::UtilityFunction do
|
|
74
73
|
class C
|
75
74
|
def m1(a) a.to_s; end
|
76
75
|
def m2(a) a.to_s; end
|
77
|
-
module_function :m1, m2
|
76
|
+
module_function :m1, :m2
|
78
77
|
end
|
79
78
|
EOS
|
80
79
|
expect(src).not_to reek_of(:UtilityFunction)
|
81
80
|
end
|
81
|
+
|
82
|
+
it 'does not report module functions defined by earlier modifier' do
|
83
|
+
src = <<-EOF
|
84
|
+
module M
|
85
|
+
module_function
|
86
|
+
def simple(a) a.to_s; end
|
87
|
+
end
|
88
|
+
EOF
|
89
|
+
expect(src).not_to reek_of(:UtilityFunction)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'reports functions preceded by canceled modifier' do
|
93
|
+
src = <<-EOF
|
94
|
+
module M
|
95
|
+
module_function
|
96
|
+
public
|
97
|
+
def simple(a) a.to_s; end
|
98
|
+
end
|
99
|
+
EOF
|
100
|
+
expect(src).to reek_of(:UtilityFunction)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'does not report when module_function is called in separate scope' do
|
104
|
+
src = <<-EOF
|
105
|
+
class C
|
106
|
+
def m(a) a.to_s; end
|
107
|
+
begin
|
108
|
+
module_function :m
|
109
|
+
end
|
110
|
+
end
|
111
|
+
EOF
|
112
|
+
expect(src).not_to reek_of(:UtilityFunction)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'does not report when module_function modifier is called in separate scope' do
|
116
|
+
src = <<-EOF
|
117
|
+
class C
|
118
|
+
begin
|
119
|
+
module_function
|
120
|
+
end
|
121
|
+
def m(a) a.to_s; end
|
122
|
+
end
|
123
|
+
EOF
|
124
|
+
expect(src).not_to reek_of(:UtilityFunction)
|
125
|
+
end
|
82
126
|
end
|
83
127
|
end
|
84
128
|
|
@@ -1,87 +1,83 @@
|
|
1
|
+
require 'pathname'
|
1
2
|
require_relative '../../spec_helper'
|
3
|
+
require_relative '../../../lib/reek/configuration/app_configuration'
|
2
4
|
require_relative '../../../lib/reek/source/source_locator'
|
3
5
|
|
4
6
|
RSpec.describe Reek::Source::SourceLocator do
|
5
7
|
describe '#sources' do
|
6
8
|
context 'applied to hidden directories' do
|
7
|
-
let(:path) { '
|
8
|
-
let(:
|
9
|
-
['
|
9
|
+
let(:path) { SAMPLES_PATH.join('source_with_hidden_directories') }
|
10
|
+
let(:expected_paths) do
|
11
|
+
[SAMPLES_PATH.join('source_with_hidden_directories/uncommunicative_parameter_name.rb')]
|
10
12
|
end
|
11
|
-
let(:
|
12
|
-
['
|
13
|
+
let(:paths_that_are_expected_to_be_ignored) do
|
14
|
+
[SAMPLES_PATH.join('source_with_hidden_directories/.hidden/\
|
15
|
+
uncommunicative_parameter_nameicative_method_name.rb')]
|
13
16
|
end
|
14
17
|
|
15
18
|
it 'does not scan hidden directories' do
|
16
19
|
sources = described_class.new([path]).sources
|
17
20
|
|
18
|
-
expect(sources.
|
19
|
-
|
20
|
-
|
21
|
-
expect(sources.map(&:path)).to eq expected_files
|
21
|
+
expect(sources).not_to include(*paths_that_are_expected_to_be_ignored)
|
22
|
+
expect(sources).to eq expected_paths
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
26
|
context 'exclude paths' do
|
26
|
-
let(:
|
27
|
-
|
28
|
-
|
27
|
+
let(:configuration) do
|
28
|
+
test_configuration_for(SAMPLES_PATH.join('configuration/with_excluded_paths.reek'))
|
29
|
+
end
|
30
|
+
let(:path) { SAMPLES_PATH.join('source_with_exclude_paths') }
|
31
|
+
let(:paths_that_are_expected_to_be_ignored) do
|
29
32
|
[
|
30
|
-
'
|
31
|
-
'
|
33
|
+
SAMPLES_PATH.join('source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb'),
|
34
|
+
SAMPLES_PATH.join('source_with_exclude_paths/nested/' \
|
35
|
+
'ignore_me_as_well/irresponsible_module.rb')
|
32
36
|
]
|
33
37
|
end
|
34
38
|
|
35
39
|
it 'does not use excluded paths' do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
expect(sources.map(&:path).sort).
|
40
|
-
not_to include(*files_that_are_expected_to_be_ignored)
|
40
|
+
sources = described_class.new([path], configuration: configuration).sources
|
41
|
+
expect(sources).not_to include(*paths_that_are_expected_to_be_ignored)
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
43
|
+
expect(sources).to eq [
|
44
|
+
SAMPLES_PATH.join('source_with_exclude_paths/nested/uncommunicative_parameter_name.rb')
|
45
|
+
]
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
context 'non-ruby
|
50
|
-
let(:path) { '
|
51
|
-
let(:
|
52
|
-
['
|
49
|
+
context 'non-ruby paths' do
|
50
|
+
let(:path) { SAMPLES_PATH.join('source_with_non_ruby_files') }
|
51
|
+
let(:expected_sources) do
|
52
|
+
[SAMPLES_PATH.join('source_with_non_ruby_files/uncommunicative_parameter_name.rb')]
|
53
53
|
end
|
54
|
-
let(:
|
54
|
+
let(:paths_that_are_expected_to_be_ignored) do
|
55
55
|
[
|
56
|
-
'
|
57
|
-
'
|
56
|
+
SAMPLES_PATH.join('source_with_non_ruby_files/gibberish'),
|
57
|
+
SAMPLES_PATH.join('source_with_non_ruby_files/python_source.py')
|
58
58
|
]
|
59
59
|
end
|
60
60
|
|
61
|
-
it 'does only use ruby source
|
61
|
+
it 'does only use ruby source paths' do
|
62
62
|
sources = described_class.new([path]).sources
|
63
63
|
|
64
|
-
expect(sources.
|
65
|
-
not_to include(*files_that_are_expected_to_be_ignored)
|
64
|
+
expect(sources).not_to include(*paths_that_are_expected_to_be_ignored)
|
66
65
|
|
67
|
-
expect(sources
|
66
|
+
expect(sources).to eq expected_sources
|
68
67
|
end
|
69
68
|
end
|
70
69
|
|
71
70
|
context 'passing "." or "./" as argument' do
|
72
|
-
let(:
|
73
|
-
[
|
74
|
-
'spec/spec_helper.rb',
|
75
|
-
'lib/reek.rb'
|
76
|
-
]
|
71
|
+
let(:expected_sources) do
|
72
|
+
[Pathname.new('spec/spec_helper.rb'), Pathname.new('lib/reek.rb')]
|
77
73
|
end
|
78
74
|
|
79
75
|
it 'expands it correctly' do
|
80
|
-
sources_for_dot = described_class.new(['.']).sources
|
81
|
-
sources_for_dot_slash = described_class.new(['./']).sources
|
76
|
+
sources_for_dot = described_class.new([Pathname.new('.')]).sources
|
77
|
+
sources_for_dot_slash = described_class.new([Pathname.new('./')]).sources
|
82
78
|
|
83
|
-
expect(sources_for_dot
|
84
|
-
expect(sources_for_dot
|
79
|
+
expect(sources_for_dot).to include(*expected_sources)
|
80
|
+
expect(sources_for_dot).to eq(sources_for_dot_slash)
|
85
81
|
end
|
86
82
|
end
|
87
83
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'pathname'
|
1
2
|
require_relative '../../spec_helper'
|
2
3
|
require_relative '../../../lib/reek/spec'
|
3
4
|
|
@@ -56,8 +57,8 @@ RSpec.describe Reek::Spec::ShouldReekOf do
|
|
56
57
|
|
57
58
|
context 'checking code in a File' do
|
58
59
|
before :each do
|
59
|
-
@clean_file =
|
60
|
-
@smelly_file =
|
60
|
+
@clean_file = Pathname.glob("#{SAMPLES_PATH}/three_clean_files/*.rb").first
|
61
|
+
@smelly_file = Pathname.glob("#{SAMPLES_PATH}/two_smelly_files/*.rb").first
|
61
62
|
@matcher = Reek::Spec::ShouldReekOf.new(:UncommunicativeVariableName,
|
62
63
|
name: '@s')
|
63
64
|
end
|
@@ -2,9 +2,8 @@ require_relative '../../spec_helper'
|
|
2
2
|
require_relative '../../../lib/reek/spec'
|
3
3
|
|
4
4
|
RSpec.describe Reek::Spec::ShouldReek do
|
5
|
-
let(:matcher) { Reek::Spec::ShouldReek.new }
|
6
|
-
|
7
5
|
describe 'checking code in a string' do
|
6
|
+
let(:matcher) { Reek::Spec::ShouldReek.new }
|
8
7
|
let(:clean_code) { 'def good() true; end' }
|
9
8
|
let(:smelly_code) { 'def x() y = 4; end' }
|
10
9
|
|
@@ -23,27 +22,36 @@ RSpec.describe Reek::Spec::ShouldReek do
|
|
23
22
|
end
|
24
23
|
|
25
24
|
describe 'checking code in a File' do
|
26
|
-
let(:clean_file) {
|
27
|
-
let(:smelly_file) {
|
28
|
-
let(:masked_file) {
|
25
|
+
let(:clean_file) { SAMPLES_PATH.join('three_clean_files/clean_one.rb') }
|
26
|
+
let(:smelly_file) { SAMPLES_PATH.join('two_smelly_files/dirty_one.rb') }
|
27
|
+
let(:masked_file) { SAMPLES_PATH.join('clean_due_to_masking/dirty_one.rb') }
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
end
|
29
|
+
context 'matcher without masking' do
|
30
|
+
let(:matcher) { Reek::Spec::ShouldReek.new }
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
it 'matches a smelly File' do
|
33
|
+
expect(matcher.matches?(smelly_file)).to be_truthy
|
34
|
+
end
|
37
35
|
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
it 'doesnt match a fragrant File' do
|
37
|
+
expect(matcher.matches?(clean_file)).to be_falsey
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'reports the smells when should_not fails' do
|
41
|
+
matcher.matches?(smelly_file)
|
42
|
+
expect(matcher.failure_message_when_negated).to match('UncommunicativeVariableName')
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
context 'matcher without masking' do
|
47
|
+
let(:path) { SAMPLES_PATH.join('clean_due_to_masking/masked.reek') }
|
48
|
+
let(:configuration) { test_configuration_for(path) }
|
49
|
+
let(:matcher) { Reek::Spec::ShouldReek.new configuration }
|
50
|
+
let(:masked_file) { SAMPLES_PATH.join('clean_due_to_masking/dirty_one.rb') }
|
51
|
+
|
52
|
+
it 'masks smells using the relevant configuration' do
|
53
|
+
expect(matcher.matches?(masked_file)).to be_falsey
|
54
|
+
end
|
47
55
|
end
|
48
56
|
end
|
49
57
|
end
|
@@ -1,34 +1,225 @@
|
|
1
1
|
require_relative '../spec_helper'
|
2
2
|
require_relative '../../lib/reek/tree_walker'
|
3
|
+
require_relative '../../lib/reek/source/source_code'
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
class Fred; end').not_to reek
|
5
|
+
# Dummy repository to inject into TreeWalker in order to count statements in
|
6
|
+
# all contexts.
|
7
|
+
class TestSmellRepository
|
8
|
+
attr_reader :num_statements
|
9
|
+
def examine(context)
|
10
|
+
@num_statements = context.num_statements
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
def process_method(source)
|
15
|
+
exp = Reek::Source::SourceCode.from(source).syntax_tree
|
16
|
+
repository = TestSmellRepository.new
|
17
|
+
Reek::TreeWalker.new(repository, exp).walk
|
18
|
+
repository
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
when block_given? then yield.to_sql
|
27
|
-
else args.to_sql
|
28
|
-
end
|
29
|
-
self
|
21
|
+
def process_singleton_method(source)
|
22
|
+
exp = Reek::Source::SourceCode.from(source).syntax_tree
|
23
|
+
repository = TestSmellRepository.new
|
24
|
+
Reek::TreeWalker.new(repository, exp).walk
|
25
|
+
repository
|
30
26
|
end
|
31
|
-
|
32
|
-
|
27
|
+
|
28
|
+
RSpec.describe Reek::TreeWalker, 'statement counting' do
|
29
|
+
it 'counts 1 assignment' do
|
30
|
+
method = process_method('def one() val = 4; end')
|
31
|
+
expect(method.num_statements).to eq(1)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'counts 3 assignments' do
|
35
|
+
method = process_method('def one() val = 4; val = 4; val = 4; end')
|
36
|
+
expect(method.num_statements).to eq(3)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'counts 1 attr assignment' do
|
40
|
+
method = process_method('def one() val[0] = 4; end')
|
41
|
+
expect(method.num_statements).to eq(1)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'counts 1 increment assignment' do
|
45
|
+
method = process_method('def one() val += 4; end')
|
46
|
+
expect(method.num_statements).to eq(1)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'counts 1 increment attr assignment' do
|
50
|
+
method = process_method('def one() val[0] += 4; end')
|
51
|
+
expect(method.num_statements).to eq(1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'counts 1 nested assignment' do
|
55
|
+
method = process_method('def one() val = fred = 4; end')
|
56
|
+
expect(method.num_statements).to eq(1)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'counts returns' do
|
60
|
+
method = process_method('def one() val = 4; true; end')
|
61
|
+
expect(method.num_statements).to eq(2)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'counts nil returns' do
|
65
|
+
method = process_method('def one() val = 4; nil; end')
|
66
|
+
expect(method.num_statements).to eq(2)
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'with control statements' do
|
70
|
+
it 'counts 1 statement in a conditional expression' do
|
71
|
+
method = process_method('def one() if val == 4; callee(); end; end')
|
72
|
+
expect(method.num_statements).to eq(1)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'counts 3 statements in a conditional expression' do
|
76
|
+
method = process_method('def one() if val == 4; callee(); callee(); callee(); end; end')
|
77
|
+
expect(method.num_statements).to eq(3)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'counts 1 statements in an else' do
|
81
|
+
method = process_method('def one() if val == 4; callee(); else; callee(); end; end')
|
82
|
+
expect(method.num_statements).to eq(2)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'counts 3 statements in an else' do
|
86
|
+
method = process_method('
|
87
|
+
def one()
|
88
|
+
if val == 4
|
89
|
+
callee(); callee(); callee()
|
90
|
+
else
|
91
|
+
callee(); callee(); callee()
|
92
|
+
end
|
93
|
+
end
|
94
|
+
')
|
95
|
+
expect(method.num_statements).to eq(6)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'does not count empty conditional expression' do
|
99
|
+
method = process_method('def one() if val == 4; ; end; end')
|
100
|
+
expect(method.num_statements).to eq(0)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'does not count empty else' do
|
104
|
+
method = process_method('def one() if val == 4; ; else; ; end; end')
|
105
|
+
expect(method.num_statements).to eq(0)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'counts extra statements in an if condition' do
|
109
|
+
method = process_method('def one() if begin val = callee(); val < 4 end; end; end')
|
110
|
+
expect(method.num_statements).to eq(1)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'counts 1 statement in a while loop' do
|
114
|
+
method = process_method('def one() while val < 4; callee(); end; end')
|
115
|
+
expect(method.num_statements).to eq(1)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'counts 3 statements in a while loop' do
|
119
|
+
source = 'def one() while val < 4; callee(); callee(); callee(); end; end'
|
120
|
+
expect(process_method(source).num_statements).to eq(3)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'counts extra statements in a while condition' do
|
124
|
+
method = process_method('def one() while begin val = callee(); val < 4 end; end; end')
|
125
|
+
expect(method.num_statements).to eq(1)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'counts 1 statement in a until loop' do
|
129
|
+
method = process_method('def one() until val < 4; callee(); end; end')
|
130
|
+
expect(method.num_statements).to eq(1)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'counts 3 statements in a until loop' do
|
134
|
+
source = 'def one() until val < 4; callee(); callee(); callee(); end; end'
|
135
|
+
expect(process_method(source).num_statements).to eq(3)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'counts 1 statement in a for loop' do
|
139
|
+
method = process_method('def one() for i in 0..4; callee(); end; end')
|
140
|
+
expect(method.num_statements).to eq(1)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'counts 3 statements in a for loop' do
|
144
|
+
source = 'def one() for i in 0..4; callee(); callee(); callee(); end; end'
|
145
|
+
expect(process_method(source).num_statements).to eq(3)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'counts 1 statement in a rescue' do
|
149
|
+
method = process_method('def one() begin; callee(); rescue; callee(); end; end')
|
150
|
+
expect(method.num_statements).to eq(2)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'counts 3 statements in a rescue' do
|
154
|
+
method = process_method('
|
155
|
+
def one()
|
156
|
+
begin
|
157
|
+
callee(); callee(); callee()
|
158
|
+
rescue
|
159
|
+
callee(); callee(); callee()
|
160
|
+
end
|
161
|
+
end
|
162
|
+
')
|
163
|
+
expect(method.num_statements).to eq(6)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'counts 1 statement in a when' do
|
167
|
+
method = process_method('def one() case fred; when "hi"; callee(); end; end')
|
168
|
+
expect(method.num_statements).to eq(1)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'counts 3 statements in a when' do
|
172
|
+
method = process_method('
|
173
|
+
def one()
|
174
|
+
case fred
|
175
|
+
when "hi" then callee(); callee()
|
176
|
+
when "lo" then callee()
|
177
|
+
end
|
178
|
+
end
|
179
|
+
')
|
180
|
+
expect(method.num_statements).to eq(3)
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'counts 1 statement in a case else' do
|
184
|
+
source = 'def one() case fred; when "hi"; callee(); else; callee(); end; end'
|
185
|
+
expect(process_method(source).num_statements).to eq(2)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'counts 3 statements in a case else' do
|
189
|
+
method = process_method('
|
190
|
+
def one()
|
191
|
+
case fred
|
192
|
+
when "hi" then callee(); callee(); callee()
|
193
|
+
else callee(); callee(); callee()
|
194
|
+
end
|
195
|
+
end
|
196
|
+
')
|
197
|
+
expect(method.num_statements).to eq(6)
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'does not count empty case' do
|
201
|
+
method = process_method('def one() case fred; when "hi"; ; when "lo"; ; end; end')
|
202
|
+
expect(method.num_statements).to eq(0)
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'does not count empty case else' do
|
206
|
+
method = process_method('def one() case fred; when "hi"; ; else; ; end; end')
|
207
|
+
expect(method.num_statements).to eq(0)
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'counts 2 statement in an iterator' do
|
211
|
+
method = process_method('def one() fred.each do; callee(); end; end')
|
212
|
+
expect(method.num_statements).to eq(2)
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'counts 4 statements in an iterator' do
|
216
|
+
source = 'def one() fred.each do; callee(); callee(); callee(); end; end'
|
217
|
+
expect(process_method(source).num_statements).to eq(4)
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'counts 1 statement in a singleton method' do
|
221
|
+
method = process_singleton_method('def self.foo; callee(); end')
|
222
|
+
expect(method.num_statements).to eq(1)
|
223
|
+
end
|
33
224
|
end
|
34
225
|
end
|