rubocop-rspec 1.39.0 → 1.43.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.md +47 -0
- data/CODE_OF_CONDUCT.md +17 -0
- data/README.md +1 -61
- data/config/default.yml +148 -20
- data/lib/rubocop-rspec.rb +4 -1
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +12 -19
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +12 -19
- data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
- data/lib/rubocop/cop/rspec/around_block.rb +1 -1
- data/lib/rubocop/cop/rspec/base.rb +74 -0
- data/lib/rubocop/cop/rspec/be.rb +2 -2
- data/lib/rubocop/cop/rspec/be_eql.rb +6 -6
- data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +19 -17
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +14 -12
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +27 -12
- data/lib/rubocop/cop/rspec/context_method.rb +7 -9
- data/lib/rubocop/cop/rspec/context_wording.rb +3 -3
- data/lib/rubocop/cop/rspec/cop.rb +2 -86
- data/lib/rubocop/cop/rspec/describe_class.rb +20 -27
- data/lib/rubocop/cop/rspec/describe_method.rb +14 -6
- data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -2
- data/lib/rubocop/cop/rspec/described_class.rb +12 -9
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
- data/lib/rubocop/cop/rspec/dialect.rb +5 -12
- data/lib/rubocop/cop/rspec/empty_example_group.rb +91 -7
- data/lib/rubocop/cop/rspec/empty_hook.rb +6 -10
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +5 -7
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +5 -9
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +8 -8
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +5 -9
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +6 -6
- data/lib/rubocop/cop/rspec/example_length.rb +1 -1
- data/lib/rubocop/cop/rspec/example_without_description.rb +1 -1
- data/lib/rubocop/cop/rspec/example_wording.rb +10 -11
- data/lib/rubocop/cop/rspec/expect_actual.rb +8 -11
- data/lib/rubocop/cop/rspec/expect_change.rb +10 -35
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +3 -3
- data/lib/rubocop/cop/rspec/expect_output.rb +2 -2
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +24 -21
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +20 -22
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +7 -8
- data/lib/rubocop/cop/rspec/file_path.rb +54 -20
- data/lib/rubocop/cop/rspec/focus.rb +7 -11
- data/lib/rubocop/cop/rspec/hook_argument.rb +16 -23
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +13 -14
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_expect.rb +7 -15
- data/lib/rubocop/cop/rspec/implicit_subject.rb +16 -11
- data/lib/rubocop/cop/rspec/instance_spy.rb +18 -12
- data/lib/rubocop/cop/rspec/instance_variable.rb +4 -8
- data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +3 -6
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +5 -6
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/leading_subject.rb +24 -21
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +2 -5
- data/lib/rubocop/cop/rspec/let_before_examples.rb +13 -11
- data/lib/rubocop/cop/rspec/let_setup.rb +21 -6
- data/lib/rubocop/cop/rspec/message_chain.rb +7 -6
- data/lib/rubocop/cop/rspec/message_expectation.rb +2 -2
- data/lib/rubocop/cop/rspec/message_spies.rb +2 -3
- data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_describes.rb +11 -8
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +7 -11
- data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +148 -0
- data/lib/rubocop/cop/rspec/multiple_subjects.rb +18 -19
- data/lib/rubocop/cop/rspec/named_subject.rb +2 -2
- data/lib/rubocop/cop/rspec/nested_groups.rb +12 -13
- data/lib/rubocop/cop/rspec/not_to_not.rb +5 -6
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/pending.rb +1 -1
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +32 -69
- data/lib/rubocop/cop/rspec/rails/http_status.rb +7 -9
- data/lib/rubocop/cop/rspec/receive_counts.rb +15 -17
- data/lib/rubocop/cop/rspec/receive_never.rb +12 -12
- data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_example.rb +2 -2
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +12 -2
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
- data/lib/rubocop/cop/rspec/return_from_stub.rb +12 -22
- data/lib/rubocop/cop/rspec/scattered_let.rb +8 -11
- data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_context.rb +8 -21
- data/lib/rubocop/cop/rspec/shared_examples.rb +7 -9
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +15 -18
- data/lib/rubocop/cop/rspec/subject_stub.rb +25 -53
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
- data/lib/rubocop/cop/rspec/variable_definition.rb +56 -0
- data/lib/rubocop/cop/rspec/variable_name.rb +66 -0
- data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
- data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/yield.rb +14 -11
- data/lib/rubocop/cop/rspec_cops.rb +3 -0
- data/lib/rubocop/rspec/corrector/move_node.rb +7 -5
- data/lib/rubocop/rspec/description_extractor.rb +2 -6
- data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -10
- data/lib/rubocop/rspec/example_group.rb +21 -49
- data/lib/rubocop/rspec/factory_bot.rb +7 -1
- data/lib/rubocop/rspec/language.rb +6 -4
- data/lib/rubocop/rspec/language/node_pattern.rb +10 -1
- data/lib/rubocop/rspec/top_level_describe.rb +2 -2
- data/lib/rubocop/rspec/top_level_group.rb +57 -0
- data/lib/rubocop/rspec/variable.rb +16 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +32 -11
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'set'
|
4
|
+
|
3
5
|
module RuboCop
|
4
6
|
module Cop
|
5
7
|
module RSpec
|
@@ -19,7 +21,9 @@ module RuboCop
|
|
19
21
|
# end
|
20
22
|
# end
|
21
23
|
#
|
22
|
-
class SubjectStub <
|
24
|
+
class SubjectStub < Base
|
25
|
+
include RuboCop::RSpec::TopLevelGroup
|
26
|
+
|
23
27
|
MSG = 'Do not stub methods of the object under test.'
|
24
28
|
|
25
29
|
# @!method subject(node)
|
@@ -35,7 +39,7 @@ module RuboCop
|
|
35
39
|
# name # => :thing
|
36
40
|
# end
|
37
41
|
#
|
38
|
-
# @param node [RuboCop::Node]
|
42
|
+
# @param node [RuboCop::AST::Node]
|
39
43
|
#
|
40
44
|
# @yield [Symbol] subject name
|
41
45
|
def_node_matcher :subject, <<-PATTERN
|
@@ -73,72 +77,40 @@ module RuboCop
|
|
73
77
|
} ...)
|
74
78
|
PATTERN
|
75
79
|
|
76
|
-
def
|
77
|
-
|
80
|
+
def on_top_level_group(node)
|
81
|
+
@explicit_subjects = find_all_explicit_subjects(node)
|
78
82
|
|
79
|
-
|
83
|
+
find_subject_expectations(node) do |stub|
|
80
84
|
add_offense(stub)
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
84
88
|
private
|
85
89
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
# @yield [RuboCop::Node] message expectations for subject
|
91
|
-
def find_subject_stub(node, &block)
|
92
|
-
find_subject(node) do |subject_name, context|
|
93
|
-
find_subject_expectation(context, subject_name, &block)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# Find a subject message expectation
|
98
|
-
#
|
99
|
-
# @param node [RuboCop::Node]
|
100
|
-
# @param subject_name [Symbol] name of subject
|
101
|
-
#
|
102
|
-
# @yield [RuboCop::Node] message expectation
|
103
|
-
def find_subject_expectation(node, subject_name, &block)
|
104
|
-
# Do not search node if it is an example group with its own subject.
|
105
|
-
return if example_group?(node) && redefines_subject?(node)
|
106
|
-
|
107
|
-
# Yield the current node if it is a message expectation.
|
108
|
-
yield(node) if message_expectation?(node, subject_name)
|
90
|
+
def find_all_explicit_subjects(node)
|
91
|
+
node.each_descendant(:block).with_object({}) do |child, h|
|
92
|
+
name = subject(child)
|
93
|
+
next unless name
|
109
94
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
end
|
114
|
-
end
|
95
|
+
outer_example_group = child.each_ancestor.find do |a|
|
96
|
+
example_group?(a)
|
97
|
+
end
|
115
98
|
|
116
|
-
|
117
|
-
|
118
|
-
# @param node [RuboCop::Node]
|
119
|
-
#
|
120
|
-
# @return [Boolean]
|
121
|
-
def redefines_subject?(node)
|
122
|
-
node.each_child_node.any? do |child|
|
123
|
-
subject(child) || redefines_subject?(child)
|
99
|
+
h[outer_example_group] ||= []
|
100
|
+
h[outer_example_group] << name
|
124
101
|
end
|
125
102
|
end
|
126
103
|
|
127
|
-
|
128
|
-
|
129
|
-
# @param node [RuboCop::Node]
|
130
|
-
# @param parent [RuboCop::Node,nil]
|
131
|
-
#
|
132
|
-
# @yieldparam subject_name [Symbol] name of subject being defined
|
133
|
-
# @yieldparam parent [RuboCop::Node] parent of subject definition
|
134
|
-
def find_subject(node, parent: nil, &block)
|
135
|
-
# An implicit subject is defined by RSpec when no subject is declared
|
136
|
-
subject_name = subject(node) || :subject
|
104
|
+
def find_subject_expectations(node, subject_names = [], &block)
|
105
|
+
subject_names = @explicit_subjects[node] if @explicit_subjects[node]
|
137
106
|
|
138
|
-
|
107
|
+
expectation_detected = (subject_names + [:subject]).any? do |name|
|
108
|
+
message_expectation?(node, name)
|
109
|
+
end
|
110
|
+
return yield(node) if expectation_detected
|
139
111
|
|
140
112
|
node.each_child_node do |child|
|
141
|
-
|
113
|
+
find_subject_expectations(child, subject_names, &block)
|
142
114
|
end
|
143
115
|
end
|
144
116
|
end
|
@@ -30,7 +30,7 @@ module RuboCop
|
|
30
30
|
# }.to raise_error(/err/)
|
31
31
|
#
|
32
32
|
# expect { do_something }.not_to raise_error
|
33
|
-
class UnspecifiedException <
|
33
|
+
class UnspecifiedException < Base
|
34
34
|
MSG = 'Specify the exception being captured'
|
35
35
|
|
36
36
|
def_node_matcher :empty_raise_error_or_exception, <<-PATTERN
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that memoized helpers names are symbols or strings.
|
7
|
+
#
|
8
|
+
# @example EnforcedStyle: symbols (default)
|
9
|
+
# # bad
|
10
|
+
# subject('user') { create_user }
|
11
|
+
# let('user_name') { 'Adam' }
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# subject(:user) { create_user }
|
15
|
+
# let(:user_name) { 'Adam' }
|
16
|
+
#
|
17
|
+
# @example EnforcedStyle: strings
|
18
|
+
# # bad
|
19
|
+
# subject(:user) { create_user }
|
20
|
+
# let(:user_name) { 'Adam' }
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# subject('user') { create_user }
|
24
|
+
# let('user_name') { 'Adam' }
|
25
|
+
class VariableDefinition < Base
|
26
|
+
include ConfigurableEnforcedStyle
|
27
|
+
include RuboCop::RSpec::Variable
|
28
|
+
|
29
|
+
MSG = 'Use %<style>s for variable names.'
|
30
|
+
|
31
|
+
def on_send(node)
|
32
|
+
variable_definition?(node) do |variable|
|
33
|
+
if style_violation?(variable)
|
34
|
+
add_offense(variable, message: format(MSG, style: style))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def style_violation?(variable)
|
42
|
+
style == :symbols && string?(variable) ||
|
43
|
+
style == :strings && symbol?(variable)
|
44
|
+
end
|
45
|
+
|
46
|
+
def string?(node)
|
47
|
+
node.str_type?
|
48
|
+
end
|
49
|
+
|
50
|
+
def symbol?(node)
|
51
|
+
node.sym_type? || node.dsym_type?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that memoized helper names use the configured style.
|
7
|
+
#
|
8
|
+
# Variables can be excluded from checking using the `IgnoredPatterns`
|
9
|
+
# option.
|
10
|
+
#
|
11
|
+
# @example EnforcedStyle: snake_case (default)
|
12
|
+
# # bad
|
13
|
+
# subject(:userName1) { 'Adam' }
|
14
|
+
# let(:userName2) { 'Adam' }
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# subject(:user_name_1) { 'Adam' }
|
18
|
+
# let(:user_name_2) { 'Adam' }
|
19
|
+
#
|
20
|
+
# @example EnforcedStyle: camelCase
|
21
|
+
# # bad
|
22
|
+
# subject(:user_name_1) { 'Adam' }
|
23
|
+
# let(:user_name_2) { 'Adam' }
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# subject(:userName1) { 'Adam' }
|
27
|
+
# let(:userName2) { 'Adam' }
|
28
|
+
#
|
29
|
+
# @example IgnoredPatterns configuration
|
30
|
+
#
|
31
|
+
# # rubocop.yml
|
32
|
+
# # RSpec/VariableName:
|
33
|
+
# # EnforcedStyle: snake_case
|
34
|
+
# # IgnoredPatterns:
|
35
|
+
# # - ^userFood
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# # okay because it matches the `^userFood` regex in `IgnoredPatterns`
|
39
|
+
# subject(:userFood_1) { 'spaghetti' }
|
40
|
+
# let(:userFood_2) { 'fettuccine' }
|
41
|
+
#
|
42
|
+
class VariableName < Base
|
43
|
+
include ConfigurableNaming
|
44
|
+
include IgnoredPattern
|
45
|
+
include RuboCop::RSpec::Variable
|
46
|
+
|
47
|
+
MSG = 'Use %<style>s for variable names.'
|
48
|
+
|
49
|
+
def on_send(node)
|
50
|
+
variable_definition?(node) do |variable|
|
51
|
+
return if variable.dstr_type? || variable.dsym_type?
|
52
|
+
return if matches_ignored_pattern?(variable.value)
|
53
|
+
|
54
|
+
check_name(node, variable.value, variable.loc.expression)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def message(style)
|
61
|
+
format(MSG, style: style)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -22,7 +22,7 @@ module RuboCop
|
|
22
22
|
# let(:foo) do
|
23
23
|
# instance_double("ClassName", method_name: 'returned value')
|
24
24
|
# end
|
25
|
-
class VerifiedDoubles <
|
25
|
+
class VerifiedDoubles < Base
|
26
26
|
MSG = 'Prefer using verifying doubles over normal doubles.'
|
27
27
|
|
28
28
|
def_node_matcher :unverified_double, <<-PATTERN
|
@@ -11,7 +11,8 @@ module RuboCop
|
|
11
11
|
#
|
12
12
|
# # good
|
13
13
|
# expect(foo).to be(:bar).and_yield(1)
|
14
|
-
class Yield <
|
14
|
+
class Yield < Base
|
15
|
+
extend AutoCorrector
|
15
16
|
include RangeHelp
|
16
17
|
|
17
18
|
MSG = 'Use `.and_yield`.'
|
@@ -27,22 +28,24 @@ module RuboCop
|
|
27
28
|
|
28
29
|
block_arg(node.arguments) do |block|
|
29
30
|
if calling_block?(node.body, block)
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
31
|
+
range = block_range(node)
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
)
|
40
|
-
corrector.replace(node_range, generate_replacement(node.body))
|
33
|
+
add_offense(range) do |corrector|
|
34
|
+
autocorrect(corrector, node, range)
|
35
|
+
end
|
36
|
+
end
|
41
37
|
end
|
42
38
|
end
|
43
39
|
|
44
40
|
private
|
45
41
|
|
42
|
+
def autocorrect(corrector, node, range)
|
43
|
+
corrector.replace(
|
44
|
+
range_with_surrounding_space(range: range, side: :left),
|
45
|
+
generate_replacement(node.body)
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
46
49
|
def calling_block?(node, block)
|
47
50
|
if node.begin_type?
|
48
51
|
node.each_child_node.all? { |child| block_call?(child, block) }
|
@@ -65,6 +65,7 @@ require_relative 'rspec/message_spies'
|
|
65
65
|
require_relative 'rspec/missing_example_group_argument'
|
66
66
|
require_relative 'rspec/multiple_describes'
|
67
67
|
require_relative 'rspec/multiple_expectations'
|
68
|
+
require_relative 'rspec/multiple_memoized_helpers'
|
68
69
|
require_relative 'rspec/multiple_subjects'
|
69
70
|
require_relative 'rspec/named_subject'
|
70
71
|
require_relative 'rspec/nested_groups'
|
@@ -86,6 +87,8 @@ require_relative 'rspec/shared_examples'
|
|
86
87
|
require_relative 'rspec/single_argument_message_chain'
|
87
88
|
require_relative 'rspec/subject_stub'
|
88
89
|
require_relative 'rspec/unspecified_exception'
|
90
|
+
require_relative 'rspec/variable_definition'
|
91
|
+
require_relative 'rspec/variable_name'
|
89
92
|
require_relative 'rspec/verified_doubles'
|
90
93
|
require_relative 'rspec/void_expect'
|
91
94
|
require_relative 'rspec/yield'
|
@@ -16,19 +16,21 @@ module RuboCop
|
|
16
16
|
@processed_source = processed_source # used by RangeHelp
|
17
17
|
end
|
18
18
|
|
19
|
-
def move_before(other)
|
19
|
+
def move_before(other)
|
20
20
|
position = other.loc.expression
|
21
|
-
indent =
|
21
|
+
indent = ' ' * other.loc.column
|
22
|
+
newline_indent = "\n#{indent}"
|
22
23
|
|
23
|
-
corrector.insert_before(position, source(original) +
|
24
|
+
corrector.insert_before(position, source(original) + newline_indent)
|
24
25
|
corrector.remove(node_range_with_surrounding_space(original))
|
25
26
|
end
|
26
27
|
|
27
28
|
def move_after(other)
|
28
29
|
position = final_end_location(other)
|
29
|
-
indent =
|
30
|
+
indent = ' ' * other.loc.column
|
31
|
+
newline_indent = "\n#{indent}"
|
30
32
|
|
31
|
-
corrector.insert_after(position,
|
33
|
+
corrector.insert_after(position, newline_indent + source(original))
|
32
34
|
corrector.remove(node_range_with_surrounding_space(original))
|
33
35
|
end
|
34
36
|
|
@@ -21,7 +21,7 @@ module RuboCop
|
|
21
21
|
|
22
22
|
# Decorator of a YARD code object for working with documented rspec cops
|
23
23
|
class CodeObject
|
24
|
-
|
24
|
+
COP_CLASS_NAME = 'RuboCop::Cop::RSpec::Base'
|
25
25
|
RSPEC_NAMESPACE = 'RuboCop::Cop::RSpec'
|
26
26
|
|
27
27
|
def initialize(yardoc)
|
@@ -68,11 +68,7 @@ module RuboCop
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def cop_subclass?
|
71
|
-
|
72
|
-
# RuboCop::Cop::WorkaroundCop are shown as having RuboCop::Cop as
|
73
|
-
# superclass, while all the following classes are listed as having
|
74
|
-
# RuboCop::Cop::RSpec::Cop as their superclass.
|
75
|
-
COP_CLASS_NAMES.include?(yardoc.superclass.path)
|
71
|
+
yardoc.superclass.path == COP_CLASS_NAME
|
76
72
|
end
|
77
73
|
|
78
74
|
def abstract?
|
@@ -2,12 +2,23 @@
|
|
2
2
|
|
3
3
|
module RuboCop
|
4
4
|
module RSpec
|
5
|
-
# Helps determine the offending location if there is not
|
5
|
+
# Helps determine the offending location if there is not an empty line
|
6
6
|
# following the node. Allows comments to follow directly after.
|
7
|
-
module
|
7
|
+
module EmptyLineSeparation
|
8
8
|
include FinalEndLocation
|
9
9
|
include RuboCop::Cop::RangeHelp
|
10
10
|
|
11
|
+
def missing_separating_line_offense(node)
|
12
|
+
return if last_child?(node)
|
13
|
+
|
14
|
+
missing_separating_line(node) do |location|
|
15
|
+
msg = yield(node.method_name)
|
16
|
+
add_offense(location, message: msg) do |corrector|
|
17
|
+
corrector.insert_after(location.end, "\n")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
11
22
|
def missing_separating_line(node)
|
12
23
|
line = final_end_location(node).line
|
13
24
|
|
@@ -32,14 +43,6 @@ module RuboCop
|
|
32
43
|
|
33
44
|
node.equal?(node.parent.children.last)
|
34
45
|
end
|
35
|
-
|
36
|
-
def autocorrect(node)
|
37
|
-
lambda do |corrector|
|
38
|
-
missing_separating_line(node) do |location|
|
39
|
-
corrector.insert_after(location.end, "\n")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
@@ -14,72 +14,44 @@ module RuboCop
|
|
14
14
|
ExampleGroups::ALL + SharedGroups::ALL + Includes::ALL
|
15
15
|
).block_pattern
|
16
16
|
|
17
|
+
def lets
|
18
|
+
find_all_in_scope(node, :let?)
|
19
|
+
end
|
20
|
+
|
17
21
|
def subjects
|
18
|
-
|
22
|
+
find_all_in_scope(node, :subject?)
|
19
23
|
end
|
20
24
|
|
21
25
|
def examples
|
22
|
-
|
26
|
+
find_all_in_scope(node, :example?).map(&Example.public_method(:new))
|
23
27
|
end
|
24
28
|
|
25
29
|
def hooks
|
26
|
-
|
30
|
+
find_all_in_scope(node, :hook?).map(&Hook.public_method(:new))
|
27
31
|
end
|
28
32
|
|
29
33
|
private
|
30
34
|
|
31
|
-
|
32
|
-
node.each_child_node.flat_map do |child|
|
33
|
-
find_subjects(child)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def find_subjects(node)
|
38
|
-
return [] if scope_change?(node)
|
39
|
-
|
40
|
-
if subject?(node)
|
41
|
-
[node]
|
42
|
-
else
|
43
|
-
subjects_in_scope(node)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def hooks_in_scope(node)
|
48
|
-
node.each_child_node.flat_map do |child|
|
49
|
-
find_hooks(child)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def find_hooks(node)
|
54
|
-
return [] if scope_change?(node) || example?(node)
|
55
|
-
|
56
|
-
if hook?(node)
|
57
|
-
[node]
|
58
|
-
else
|
59
|
-
hooks_in_scope(node)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def examples_in_scope(node, &blk)
|
64
|
-
node.each_child_node.flat_map do |child|
|
65
|
-
find_examples(child, &blk)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Recursively search for examples within the current scope
|
35
|
+
# Recursively search for predicate within the current scope
|
70
36
|
#
|
71
|
-
# Searches node
|
37
|
+
# Searches node and halts when a scope change is detected
|
72
38
|
#
|
73
|
-
# @param node [RuboCop::Node] node to recursively search
|
39
|
+
# @param node [RuboCop::AST::Node] node to recursively search
|
74
40
|
#
|
75
|
-
# @return [Array<RuboCop::Node>] discovered
|
76
|
-
def
|
77
|
-
|
41
|
+
# @return [Array<RuboCop::AST::Node>] discovered nodes
|
42
|
+
def find_all_in_scope(node, predicate)
|
43
|
+
node.each_child_node.flat_map do |child|
|
44
|
+
find_all(child, predicate)
|
45
|
+
end
|
46
|
+
end
|
78
47
|
|
79
|
-
|
48
|
+
def find_all(node, predicate)
|
49
|
+
if public_send(predicate, node)
|
80
50
|
[node]
|
51
|
+
elsif scope_change?(node) || example?(node)
|
52
|
+
[]
|
81
53
|
else
|
82
|
-
|
54
|
+
find_all_in_scope(node, predicate)
|
83
55
|
end
|
84
56
|
end
|
85
57
|
end
|