rubocop-rspec 1.6.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +23 -0
- data/Rakefile +19 -1
- data/config/default.yml +78 -15
- data/lib/rubocop-rspec.rb +19 -1
- data/lib/rubocop/cop/rspec/any_instance.rb +5 -1
- data/lib/rubocop/cop/rspec/be_eql.rb +58 -0
- data/lib/rubocop/cop/rspec/describe_class.rb +2 -3
- data/lib/rubocop/cop/rspec/describe_method.rb +4 -3
- data/lib/rubocop/cop/rspec/described_class.rb +4 -35
- data/lib/rubocop/cop/rspec/empty_example_group.rb +100 -0
- data/lib/rubocop/cop/rspec/example_length.rb +5 -2
- data/lib/rubocop/cop/rspec/example_wording.rb +5 -2
- data/lib/rubocop/cop/rspec/expect_actual.rb +79 -0
- data/lib/rubocop/cop/rspec/file_path.rb +3 -1
- data/lib/rubocop/cop/rspec/focus.rb +12 -28
- data/lib/rubocop/cop/rspec/hook_argument.rb +122 -0
- data/lib/rubocop/cop/rspec/instance_variable.rb +53 -12
- data/lib/rubocop/cop/rspec/leading_subject.rb +58 -0
- data/lib/rubocop/cop/rspec/let_setup.rb +58 -0
- data/lib/rubocop/cop/rspec/message_chain.rb +33 -0
- data/lib/rubocop/cop/rspec/message_expectation.rb +58 -0
- data/lib/rubocop/cop/rspec/multiple_describes.rb +10 -7
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +89 -0
- data/lib/rubocop/cop/rspec/named_subject.rb +10 -1
- data/lib/rubocop/cop/rspec/nested_groups.rb +125 -0
- data/lib/rubocop/cop/rspec/not_to_not.rb +3 -3
- data/lib/rubocop/cop/rspec/subject_stub.rb +136 -0
- data/lib/rubocop/cop/rspec/verified_doubles.rb +4 -1
- data/lib/rubocop/rspec.rb +10 -0
- data/lib/rubocop/rspec/config_formatter.rb +33 -0
- data/lib/rubocop/rspec/description_extractor.rb +35 -0
- data/lib/rubocop/rspec/inject.rb +2 -6
- data/lib/rubocop/rspec/language.rb +73 -0
- data/lib/rubocop/rspec/language/node_pattern.rb +16 -0
- data/lib/rubocop/rspec/spec_only.rb +61 -0
- data/lib/rubocop/rspec/top_level_describe.rb +6 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/rubocop-rspec.gemspec +1 -0
- data/spec/project/changelog_spec.rb +81 -0
- data/spec/project/default_config_spec.rb +52 -0
- data/spec/project/project_requires_spec.rb +8 -0
- data/spec/rubocop/cop/rspec/be_eql_spec.rb +59 -0
- data/spec/rubocop/cop/rspec/described_class_spec.rb +2 -2
- data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +79 -0
- data/spec/rubocop/cop/rspec/example_length_spec.rb +50 -30
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +21 -3
- data/spec/rubocop/cop/rspec/expect_actual_spec.rb +136 -0
- data/spec/rubocop/cop/rspec/file_path_spec.rb +48 -71
- data/spec/rubocop/cop/rspec/focus_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/hook_argument_spec.rb +189 -0
- data/spec/rubocop/cop/rspec/instance_variable_spec.rb +37 -0
- data/spec/rubocop/cop/rspec/leading_subject_spec.rb +54 -0
- data/spec/rubocop/cop/rspec/let_setup_spec.rb +66 -0
- data/spec/rubocop/cop/rspec/message_chain_spec.rb +21 -0
- data/spec/rubocop/cop/rspec/message_expectation_spec.rb +63 -0
- data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +84 -0
- data/spec/rubocop/cop/rspec/nested_groups_spec.rb +55 -0
- data/spec/rubocop/cop/rspec/not_to_not_spec.rb +12 -2
- data/spec/rubocop/cop/rspec/subject_stub_spec.rb +183 -0
- data/spec/rubocop/rspec/config_formatter_spec.rb +48 -0
- data/spec/rubocop/rspec/description_extractor_spec.rb +35 -0
- data/spec/rubocop/rspec/language/selector_set_spec.rb +29 -0
- data/spec/rubocop/rspec/spec_only_spec.rb +97 -0
- data/spec/shared/rspec_only_cop_behavior.rb +68 -0
- data/spec/spec_helper.rb +13 -1
- metadata +72 -5
- data/spec/project_spec.rb +0 -115
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if an example group does not include any tests.
|
7
|
+
#
|
8
|
+
# This cop is configurable using the `CustomIncludeMethods` option
|
9
|
+
#
|
10
|
+
# @example usage
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# describe Bacon do
|
14
|
+
# let(:bacon) { Bacon.new(chunkiness) }
|
15
|
+
# let(:chunkiness) { false }
|
16
|
+
#
|
17
|
+
# context 'extra chunky' do # flagged by rubocop
|
18
|
+
# let(:chunkiness) { true }
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# it 'is chunky' do
|
22
|
+
# expect(bacon.chunky?).to be_truthy
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# describe Bacon do
|
28
|
+
# let(:bacon) { Bacon.new(chunkiness) }
|
29
|
+
# let(:chunkiness) { false }
|
30
|
+
#
|
31
|
+
# it 'is chunky' do
|
32
|
+
# expect(bacon.chunky?).to be_truthy
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# @example configuration
|
37
|
+
#
|
38
|
+
# # .rubocop.yml
|
39
|
+
# RSpec/EmptyExampleGroup:
|
40
|
+
# CustomIncludeMethods:
|
41
|
+
# - include_tests
|
42
|
+
#
|
43
|
+
# # spec_helper.rb
|
44
|
+
# RSpec.configure do |config|
|
45
|
+
# config.alias_it_behaves_like_to(:include_tests)
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# # bacon_spec.rb
|
49
|
+
# describe Bacon do
|
50
|
+
# let(:bacon) { Bacon.new(chunkiness) }
|
51
|
+
# let(:chunkiness) { false }
|
52
|
+
#
|
53
|
+
# context 'extra chunky' do # not flagged by rubocop
|
54
|
+
# let(:chunkiness) { true }
|
55
|
+
#
|
56
|
+
# include_tests 'shared tests'
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
class EmptyExampleGroup < Cop
|
61
|
+
include RuboCop::RSpec::SpecOnly,
|
62
|
+
RuboCop::RSpec::Language,
|
63
|
+
RuboCop::RSpec::Language::NodePattern
|
64
|
+
|
65
|
+
MSG = 'Empty example group detected.'.freeze
|
66
|
+
|
67
|
+
def_node_search :contains_example?, <<-PATTERN
|
68
|
+
{
|
69
|
+
(send _ {
|
70
|
+
#{Examples::ALL.to_node_pattern}
|
71
|
+
:it_behaves_like
|
72
|
+
:it_should_behave_like
|
73
|
+
:include_context
|
74
|
+
:include_examples
|
75
|
+
} ...)
|
76
|
+
(send _ #custom_include? ...)
|
77
|
+
}
|
78
|
+
PATTERN
|
79
|
+
|
80
|
+
def on_block(node)
|
81
|
+
return unless example_group?(node) && !contains_example?(node)
|
82
|
+
|
83
|
+
add_offense(node.children.first, :expression)
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def custom_include?(method_name)
|
89
|
+
custom_include_methods.include?(method_name)
|
90
|
+
end
|
91
|
+
|
92
|
+
def custom_include_methods
|
93
|
+
cop_config
|
94
|
+
.fetch('CustomIncludeMethods', [])
|
95
|
+
.map(&:to_sym)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
+
# Checks for long examples.
|
7
|
+
#
|
6
8
|
# A long example is usually more difficult to understand. Consider
|
7
9
|
# extracting out some behaviour, e.g. with a `let` block, or a helper
|
8
10
|
# method.
|
@@ -24,8 +26,9 @@ module RuboCop
|
|
24
26
|
# expect(result).to be(true)
|
25
27
|
# end
|
26
28
|
class ExampleLength < Cop
|
27
|
-
include CodeLength
|
28
|
-
|
29
|
+
include RuboCop::RSpec::SpecOnly, CodeLength
|
30
|
+
|
31
|
+
EXAMPLE_BLOCKS = RuboCop::RSpec::Language::Examples::ALL
|
29
32
|
|
30
33
|
def on_block(node)
|
31
34
|
method, _args, _body = *node
|
@@ -3,8 +3,9 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# Checks that example descriptions do not start with "should".
|
7
|
+
#
|
8
|
+
# @see http://betterspecs.org/#should
|
8
9
|
#
|
9
10
|
# The autocorrect is experimental - use with care! It can be configured
|
10
11
|
# with CustomTransform (e.g. have => has) and IgnoredWords (e.g. only).
|
@@ -18,6 +19,8 @@ module RuboCop
|
|
18
19
|
# it 'finds nothing' do
|
19
20
|
# end
|
20
21
|
class ExampleWording < Cop
|
22
|
+
include RuboCop::RSpec::SpecOnly
|
23
|
+
|
21
24
|
MSG = 'Do not use should when describing your tests.'.freeze
|
22
25
|
|
23
26
|
def on_block(node) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/LineLength
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for `expect(...)` calls containing literal values.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# expect(5).to eq(price)
|
11
|
+
# expect(/foo/).to eq(pattern)
|
12
|
+
# expect("John").to eq(name)
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# expect(price).to eq(5)
|
16
|
+
# expect(pattern).to eq(/foo/)
|
17
|
+
# expect(name).to eq("John")
|
18
|
+
#
|
19
|
+
class ExpectActual < Cop
|
20
|
+
include RuboCop::RSpec::SpecOnly
|
21
|
+
|
22
|
+
MSG = 'Provide the actual you are testing to `expect(...)`'.freeze
|
23
|
+
|
24
|
+
SIMPLE_LITERALS = %i(
|
25
|
+
true
|
26
|
+
false
|
27
|
+
nil
|
28
|
+
int
|
29
|
+
float
|
30
|
+
str
|
31
|
+
sym
|
32
|
+
complex
|
33
|
+
rational
|
34
|
+
regopt
|
35
|
+
).freeze
|
36
|
+
|
37
|
+
COMPLEX_LITERALS = %i(
|
38
|
+
array
|
39
|
+
hash
|
40
|
+
pair
|
41
|
+
irange
|
42
|
+
erange
|
43
|
+
regexp
|
44
|
+
).freeze
|
45
|
+
|
46
|
+
def_node_matcher :expect, '(send _ :expect $_)'
|
47
|
+
|
48
|
+
def on_send(node)
|
49
|
+
expect_literal(node) do |argument|
|
50
|
+
add_offense(argument, :expression)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# This is not implement using a NodePattern because it seems
|
57
|
+
# to not be able to match against an explicit (nil) sexp
|
58
|
+
def expect_literal(node)
|
59
|
+
return unless (argument = expect(node))
|
60
|
+
|
61
|
+
yield(argument) if literal?(argument)
|
62
|
+
end
|
63
|
+
|
64
|
+
def literal?(node)
|
65
|
+
simple_literal?(node) || complex_literal?(node)
|
66
|
+
end
|
67
|
+
|
68
|
+
def simple_literal?(node)
|
69
|
+
SIMPLE_LITERALS.include?(node.type)
|
70
|
+
end
|
71
|
+
|
72
|
+
def complex_literal?(node)
|
73
|
+
COMPLEX_LITERALS.include?(node.type) &&
|
74
|
+
node.each_child_node.all?(&method(:literal?))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
+
# Checks that spec file paths are consistent with the test subject.
|
7
|
+
#
|
6
8
|
# Checks the path of the spec file and enforces that it reflects the
|
7
9
|
# described class/module and its optionally called out method.
|
8
10
|
#
|
@@ -15,7 +17,7 @@ module RuboCop
|
|
15
17
|
# my_class_method_spec.rb # describe MyClass, '#method'
|
16
18
|
# my_class_spec.rb # describe MyClass
|
17
19
|
class FilePath < Cop
|
18
|
-
include RuboCop::RSpec::TopLevelDescribe
|
20
|
+
include RuboCop::RSpec::SpecOnly, RuboCop::RSpec::TopLevelDescribe
|
19
21
|
|
20
22
|
MESSAGE = 'Spec path should end with `%s`'.freeze
|
21
23
|
METHOD_STRING_MATCHER = /^[\#\.].+/
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
-
# Checks if
|
6
|
+
# Checks if examples are focused.
|
7
7
|
#
|
8
8
|
# @example
|
9
9
|
# # bad
|
@@ -20,36 +20,20 @@ module RuboCop
|
|
20
20
|
# describe MyClass do
|
21
21
|
# end
|
22
22
|
class Focus < Cop
|
23
|
+
include RuboCop::RSpec::SpecOnly, RuboCop::RSpec::Language
|
24
|
+
|
23
25
|
MSG = 'Focused spec found.'.freeze
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
:scenario
|
33
|
-
:specify
|
34
|
-
:xcontext
|
35
|
-
:xdescribe
|
36
|
-
:xexample
|
37
|
-
:xfeature
|
38
|
-
:xit
|
39
|
-
:xscenario
|
40
|
-
:xspecify
|
41
|
-
'.freeze
|
27
|
+
focusable =
|
28
|
+
ExampleGroups::GROUPS +
|
29
|
+
ExampleGroups::SKIPPED +
|
30
|
+
Examples::EXAMPLES +
|
31
|
+
Examples::SKIPPED
|
32
|
+
|
33
|
+
focused = ExampleGroups::FOCUSED + Examples::FOCUSED
|
42
34
|
|
43
|
-
|
44
|
-
|
45
|
-
:fdescribe
|
46
|
-
:fexample
|
47
|
-
:ffeature
|
48
|
-
:fit
|
49
|
-
:focus
|
50
|
-
:fscenario
|
51
|
-
:fspecify
|
52
|
-
'.freeze
|
35
|
+
FOCUSABLE_SELECTORS = focusable.to_node_pattern
|
36
|
+
FOCUSING_SELECTORS = focused.to_node_pattern
|
53
37
|
|
54
38
|
FOCUS_SYMBOL = s(:sym, :focus)
|
55
39
|
FOCUS_TRUE = s(:pair, FOCUS_SYMBOL, s(:true))
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks the arguments passed to `before`, `around`, and `after`.
|
7
|
+
#
|
8
|
+
# This cop checks for consistent style when specifying RSpec
|
9
|
+
# hooks which run for each example. There are three supported
|
10
|
+
# styles: "implicit", "each", and "example." All styles have
|
11
|
+
# the same behavior.
|
12
|
+
#
|
13
|
+
# @example when configuration is `EnforcedStyle: implicit`
|
14
|
+
# # bad
|
15
|
+
# before(:each) do
|
16
|
+
# ...
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# before(:example) do
|
21
|
+
# ...
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# before do
|
26
|
+
# ...
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @example when configuration is `EnforcedStyle: each`
|
30
|
+
# # bad
|
31
|
+
# before(:example) do
|
32
|
+
# ...
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# before do
|
37
|
+
# ...
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# # good
|
41
|
+
# before(:each) do
|
42
|
+
# ...
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# @example when configuration is `EnforcedStyle: example`
|
46
|
+
# # bad
|
47
|
+
# before(:each) do
|
48
|
+
# ...
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# # bad
|
52
|
+
# before do
|
53
|
+
# ...
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# # good
|
57
|
+
# before(:example) do
|
58
|
+
# ...
|
59
|
+
# end
|
60
|
+
class HookArgument < RuboCop::Cop::Cop
|
61
|
+
include RuboCop::RSpec::Language,
|
62
|
+
RuboCop::RSpec::SpecOnly,
|
63
|
+
ConfigurableEnforcedStyle
|
64
|
+
|
65
|
+
IMPLICIT_MSG = 'Omit the default `%p` argument for RSpec hooks.'.freeze
|
66
|
+
EXPLICIT_MSG = 'Use `%p` for RSpec hooks.'.freeze
|
67
|
+
|
68
|
+
HOOKS = "{#{Hooks::ALL.to_node_pattern}}".freeze
|
69
|
+
|
70
|
+
def_node_matcher :scoped_hook, <<-PATTERN
|
71
|
+
(block $(send nil #{HOOKS} (sym ${:each :example})) ...)
|
72
|
+
PATTERN
|
73
|
+
|
74
|
+
def_node_matcher :unscoped_hook, "(block $(send nil #{HOOKS}) ...)"
|
75
|
+
|
76
|
+
def on_block(node)
|
77
|
+
hook(node) do |method_send, scope_name|
|
78
|
+
return correct_style_detected if scope_name.equal?(style)
|
79
|
+
return check_implicit(method_send) unless scope_name
|
80
|
+
|
81
|
+
style_detected(scope_name)
|
82
|
+
add_offense(method_send, :expression, explicit_message(scope_name))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def autocorrect(node)
|
87
|
+
scope = "(#{style.inspect})" unless implicit_style?
|
88
|
+
hook = "#{node.method_name}#{scope}"
|
89
|
+
|
90
|
+
lambda do |corrector|
|
91
|
+
corrector.replace(node.loc.expression, hook)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def check_implicit(method_send)
|
98
|
+
style_detected(:implicit)
|
99
|
+
return if implicit_style?
|
100
|
+
|
101
|
+
add_offense(method_send, :selector, format(EXPLICIT_MSG, style))
|
102
|
+
end
|
103
|
+
|
104
|
+
def explicit_message(scope)
|
105
|
+
if implicit_style?
|
106
|
+
format(IMPLICIT_MSG, scope)
|
107
|
+
else
|
108
|
+
format(EXPLICIT_MSG, style)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def implicit_style?
|
113
|
+
style.equal?(:implicit)
|
114
|
+
end
|
115
|
+
|
116
|
+
def hook(node, &block)
|
117
|
+
scoped_hook(node, &block) || unscoped_hook(node, &block)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -3,8 +3,12 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# Checks for instance variable usage in specs.
|
7
|
+
#
|
8
|
+
# This cop can be configured with the option `AssignmentOnly` which
|
9
|
+
# will configure the cop to only register offenses on instance
|
10
|
+
# variable usage if the instance variable is also assigned within
|
11
|
+
# the spec
|
8
12
|
#
|
9
13
|
# @example
|
10
14
|
# # bad
|
@@ -18,22 +22,59 @@ module RuboCop
|
|
18
22
|
# let(:foo) { [] }
|
19
23
|
# it { expect(foo).to be_empty }
|
20
24
|
# end
|
25
|
+
#
|
26
|
+
# @example with AssignmentOnly configuration
|
27
|
+
#
|
28
|
+
# # rubocop.yml
|
29
|
+
# RSpec/InstanceVariable:
|
30
|
+
# AssignmentOnly: false
|
31
|
+
#
|
32
|
+
# # bad
|
33
|
+
# describe MyClass do
|
34
|
+
# before { @foo = [] }
|
35
|
+
# it { expect(@foo).to be_empty }
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# # allowed
|
39
|
+
# describe MyClass do
|
40
|
+
# it { expect(@foo).to be_empty }
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# describe MyClass do
|
45
|
+
# let(:foo) { [] }
|
46
|
+
# it { expect(foo).to be_empty }
|
47
|
+
# end
|
48
|
+
#
|
21
49
|
class InstanceVariable < Cop
|
50
|
+
include RuboCop::RSpec::SpecOnly, RuboCop::RSpec::Language
|
51
|
+
|
22
52
|
MESSAGE = 'Use `let` instead of an instance variable'.freeze
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
53
|
+
|
54
|
+
EXAMPLE_GROUP_METHODS = ExampleGroups::ALL + SharedGroups::ALL
|
55
|
+
|
56
|
+
def_node_matcher :spec_group?, <<-PATTERN
|
57
|
+
(block (send _ {#{EXAMPLE_GROUP_METHODS.to_node_pattern}} ...) ...)
|
58
|
+
PATTERN
|
59
|
+
|
60
|
+
def_node_search :ivar_usage, '$(ivar $_)'
|
61
|
+
|
62
|
+
def_node_search :ivar_assigned?, '(ivasgn % ...)'
|
28
63
|
|
29
64
|
def on_block(node)
|
30
|
-
|
31
|
-
|
32
|
-
|
65
|
+
return unless spec_group?(node)
|
66
|
+
|
67
|
+
ivar_usage(node) do |ivar, name|
|
68
|
+
return if assignment_only? && !ivar_assigned?(node, name)
|
69
|
+
|
70
|
+
add_offense(ivar, :expression, MESSAGE)
|
71
|
+
end
|
33
72
|
end
|
34
73
|
|
35
|
-
|
36
|
-
|
74
|
+
private
|
75
|
+
|
76
|
+
def assignment_only?
|
77
|
+
cop_config['AssignmentOnly']
|
37
78
|
end
|
38
79
|
end
|
39
80
|
end
|