rubocop-rspec 3.4.0 → 3.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a2433cc3212de48725bca4fa2f8216ef0742950d1b0ad0a52e0d717050ede4e
4
- data.tar.gz: 3e43165a772275ece7344813b6dfc5196669763013c0bedc3b75107cf6fa0f30
3
+ metadata.gz: 5852eb2103d4a2993b2174b7e4c97f5f7f09041c49407122ab6568d744d52c09
4
+ data.tar.gz: 710d277b8be358c99cadf4ca500141d23fa73347ba3f29db0585a1e7026abd73
5
5
  SHA512:
6
- metadata.gz: 41a9171c098150e3349977cd08df5f369fe2d33c0bb4f1b29edcfb2633eae2c880ab1ff71a9c4a1ee5dc28645a6359ecd3e4ab99a822ac576523386e78364ee2
7
- data.tar.gz: af1c164ac3d8c9e9ed61611fa9877c459656f695fd45c057c776af99304fcd8471fa00d958d7bf650ba46f82056ae96accd12cfeec17eb1a00129baffdb51768
6
+ metadata.gz: e27d20e6945c05f12af9fc24e17e42691186b332611d96eb9e7a5444476de44209517ccdb4829096cff659e7a7d1b98941ff632b3f7f5a547aa4dc82d3e18e38
7
+ data.tar.gz: 93a9cb481828abc2e313129cec383d38de5261f382d7ae6fcabe42bd0146b5a134b90991df47cc0bade3c1e4266cbfcf733f35ea7bee8eafaa3e5e4236a0b3ca
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 3.5.0 (2025-02-16)
6
+
7
+ - Don't let `RSpec/PredicateMatcher` replace `respond_to?` with two arguments with the RSpec `respond_to` matcher. ([@bquorning])
8
+ - Fix `RSpec/PredicateMatcher` support for `eql` and `equal` matchers. ([@bquorning])
9
+ - Pluginfy RuboCop RSpec. ([@koic])
10
+
5
11
  ## 3.4.0 (2025-01-20)
6
12
 
7
13
  - Fix `RSpec/SortMetadata` cop to limit sorting to trailing metadata arguments. ([@cbliard])
data/README.md CHANGED
@@ -48,13 +48,13 @@ ways to do this:
48
48
  Put this into your `.rubocop.yml`.
49
49
 
50
50
  ```yaml
51
- require: rubocop-rspec
51
+ plugins: rubocop-rspec
52
52
  ```
53
53
 
54
54
  Alternatively, use the following array notation when specifying multiple extensions.
55
55
 
56
56
  ```yaml
57
- require:
57
+ plugins:
58
58
  - rubocop-other-extension
59
59
  - rubocop-rspec
60
60
  ```
@@ -62,17 +62,20 @@ require:
62
62
  Now you can run `rubocop` and it will automatically load the RuboCop RSpec
63
63
  cops together with the standard cops.
64
64
 
65
+ > [!NOTE]
66
+ > The plugin system is supported in RuboCop 1.72+. In earlier versions, use `require` instead of `plugins`.
67
+
65
68
  ### Command line
66
69
 
67
70
  ```bash
68
- rubocop --require rubocop-rspec
71
+ rubocop --plugin rubocop-rspec
69
72
  ```
70
73
 
71
74
  ### Rake task
72
75
 
73
76
  ```ruby
74
77
  RuboCop::RakeTask.new do |task|
75
- task.requires << 'rubocop-rspec'
78
+ task.plugins << 'rubocop-rspec'
76
79
  end
77
80
  ```
78
81
 
@@ -31,7 +31,7 @@ module RuboCop
31
31
 
32
32
  # @!method eq_type_with_identity?(node)
33
33
  def_node_matcher :eq_type_with_identity?, <<~PATTERN
34
- (send nil? :eq {true false nil})
34
+ (send nil? :eq {boolean nil})
35
35
  PATTERN
36
36
 
37
37
  def on_send(node)
@@ -45,7 +45,7 @@ module RuboCop
45
45
 
46
46
  # @!method eql_type_with_identity(node)
47
47
  def_node_matcher :eql_type_with_identity, <<~PATTERN
48
- (send _ :to $(send nil? :eql {true false int float sym nil}))
48
+ (send _ :to $(send nil? :eql {boolean int float sym nil}))
49
49
  PATTERN
50
50
 
51
51
  def on_send(node)
@@ -48,6 +48,10 @@ module RuboCop
48
48
  check_be_style(node)
49
49
  when :be_nil
50
50
  check_be_nil_style(node)
51
+ else
52
+ # :nocov:
53
+ :noop
54
+ # :nocov:
51
55
  end
52
56
  end
53
57
 
@@ -101,7 +101,6 @@ module RuboCop
101
101
 
102
102
  private
103
103
 
104
- # rubocop:disable Metrics/MethodLength
105
104
  def register_offense(node, change_node)
106
105
  if compound_expectations?(node)
107
106
  add_offense(node,
@@ -115,7 +114,6 @@ module RuboCop
115
114
  end
116
115
  end
117
116
  end
118
- # rubocop:enable Metrics/MethodLength
119
117
 
120
118
  def compound_expectations?(node)
121
119
  node.parent.send_type? &&
@@ -67,7 +67,6 @@ module RuboCop
67
67
  } ...) ...)
68
68
  PATTERN
69
69
 
70
- # rubocop:disable Metrics/MethodLength
71
70
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
72
71
  it_description(node) do |description_node, message|
73
72
  if message.match?(SHOULD_PREFIX)
@@ -82,7 +81,6 @@ module RuboCop
82
81
  end
83
82
  end
84
83
  end
85
- # rubocop:enable Metrics/MethodLength
86
84
 
87
85
  private
88
86
 
@@ -128,7 +126,7 @@ module RuboCop
128
126
  node.node_parts.map { |child_node| text(child_node) }.join
129
127
  when :str
130
128
  node.value
131
- when :begin
129
+ else
132
130
  node.source
133
131
  end
134
132
  end
@@ -100,7 +100,7 @@ module RuboCop
100
100
  node.node_parts.map { |child_node| text(child_node) }.join
101
101
  when :str, :sym
102
102
  node.value
103
- when :begin
103
+ else
104
104
  node.source
105
105
  end
106
106
  end
@@ -65,7 +65,7 @@ module RuboCop
65
65
  )
66
66
  PATTERN
67
67
 
68
- def on_send(node) # rubocop:disable Metrics/MethodLength
68
+ def on_send(node)
69
69
  expect_literal(node) do |actual, send_node, matcher, expected|
70
70
  next if SKIPPED_MATCHERS.include?(matcher)
71
71
 
@@ -75,23 +75,27 @@ module RuboCop
75
75
  def on_send(node)
76
76
  return if node.chained? || node.each_ancestor(:def, :defs).any?
77
77
 
78
- focus_metadata(node) do |focus|
79
- add_offense(focus) do |corrector|
80
- if focus.pair_type? || focus.str_type? || focus.sym_type?
81
- corrector.remove(with_surrounding(focus))
82
- elsif focus.send_type?
83
- correct_send(corrector, focus)
84
- end
78
+ if focused_block?(node)
79
+ on_focused_block(node)
80
+ else
81
+ metadata(node) do |focus|
82
+ on_metadata(focus)
85
83
  end
86
84
  end
87
85
  end
88
86
 
89
87
  private
90
88
 
91
- def focus_metadata(node, &block)
92
- yield(node) if focused_block?(node)
89
+ def on_focused_block(node)
90
+ add_offense(node) do |corrector|
91
+ correct_send(corrector, node)
92
+ end
93
+ end
93
94
 
94
- metadata(node, &block)
95
+ def on_metadata(node)
96
+ add_offense(node) do |corrector|
97
+ corrector.remove(with_surrounding(node))
98
+ end
95
99
  end
96
100
 
97
101
  def with_surrounding(focus)
@@ -46,7 +46,7 @@ module RuboCop
46
46
 
47
47
  ENFORCED_REPLACEMENTS = alternatives.merge(alternatives.invert).freeze
48
48
 
49
- def on_send(node) # rubocop:disable Metrics/MethodLength
49
+ def on_send(node)
50
50
  return unless (source_range = offending_expect(node))
51
51
 
52
52
  expectation_source = source_range.source
@@ -69,13 +69,13 @@ module RuboCop
69
69
  def offending_expect(node)
70
70
  case implicit_expect(node)
71
71
  when :is_expected
72
- is_expected_range(node.loc)
72
+ range_for_is_expected(node.loc)
73
73
  when :should, :should_not
74
74
  node.loc.selector
75
75
  end
76
76
  end
77
77
 
78
- def is_expected_range(source_map) # rubocop:disable Naming/PredicateName
78
+ def range_for_is_expected(source_map)
79
79
  Parser::Source::Range.new(
80
80
  source_map.expression.source_buffer,
81
81
  source_map.expression.begin_pos,
@@ -107,6 +107,10 @@ module RuboCop
107
107
  corrector.replace(node.location.selector, 'expect(subject).to')
108
108
  when :should_not
109
109
  corrector.replace(node.location.selector, 'expect(subject).not_to')
110
+ else
111
+ # :nocov:
112
+ :noop
113
+ # :nocov:
110
114
  end
111
115
  end
112
116
 
@@ -129,6 +133,10 @@ module RuboCop
129
133
  implicit_subject_in_non_its_and_non_single_line?(node)
130
134
  when :single_statement_only
131
135
  implicit_subject_in_non_its_and_non_single_statement?(node)
136
+ else
137
+ # :nocov:
138
+ :noop
139
+ # :nocov:
132
140
  end
133
141
  end
134
142
 
@@ -74,7 +74,9 @@ module RuboCop
74
74
  private
75
75
 
76
76
  SUFFIX_INDEX_REGEX = /_?\d+$/.freeze
77
+ private_constant :SUFFIX_INDEX_REGEX
77
78
  INDEX_REGEX = /\d+/.freeze
79
+ private_constant :INDEX_REGEX
78
80
 
79
81
  def filter_indexed_lets(candidates)
80
82
  candidates
@@ -80,6 +80,10 @@ module RuboCop
80
80
  MSG_RECEIVE
81
81
  when :have_received
82
82
  format(MSG_HAVE_RECEIVED, source: receiver.source)
83
+ else
84
+ # :nocov:
85
+ :noop
86
+ # :nocov:
83
87
  end
84
88
  end
85
89
  end
@@ -15,6 +15,8 @@ module RuboCop
15
15
 
16
16
  def check_inflected(node)
17
17
  predicate_in_actual?(node) do |predicate, to, matcher|
18
+ next if cannot_replace_predicate?(predicate)
19
+
18
20
  msg = message_inflected(predicate)
19
21
  add_offense(node, message: msg) do |corrector|
20
22
  remove_predicate(corrector, predicate)
@@ -35,9 +37,13 @@ module RuboCop
35
37
  $#boolean_matcher? ...)
36
38
  PATTERN
37
39
 
40
+ def cannot_replace_predicate?(send_node)
41
+ send_node.method?(:respond_to?) && send_node.arguments.length > 1
42
+ end
43
+
38
44
  # @!method be_bool?(node)
39
45
  def_node_matcher :be_bool?, <<~PATTERN
40
- (send nil? {:be :eq :eql :equal} {true false})
46
+ (send nil? {:be :eq :eql :equal} boolean)
41
47
  PATTERN
42
48
 
43
49
  # @!method be_boolthy?(node)
@@ -63,7 +69,6 @@ module RuboCop
63
69
  matcher_name: to_predicate_matcher(predicate.method_name))
64
70
  end
65
71
 
66
- # rubocop:disable Metrics/MethodLength
67
72
  def to_predicate_matcher(name)
68
73
  case name = name.to_s
69
74
  when 'is_a?'
@@ -80,7 +85,6 @@ module RuboCop
80
85
  "be_#{name[0..-2]}"
81
86
  end
82
87
  end
83
- # rubocop:enable Metrics/MethodLength
84
88
 
85
89
  def remove_predicate(corrector, predicate)
86
90
  range = predicate.loc.dot.with(
@@ -106,12 +110,16 @@ module RuboCop
106
110
 
107
111
  def true?(to_symbol, matcher)
108
112
  result = case matcher.method_name
109
- when :be, :eq
113
+ when :be, :eq, :eql, :equal
110
114
  matcher.first_argument.true_type?
111
115
  when :be_truthy, :a_truthy_value
112
116
  true
113
117
  when :be_falsey, :be_falsy, :a_falsey_value, :a_falsy_value
114
118
  false
119
+ else
120
+ # :nocov:
121
+ :noop
122
+ # :nocov:
115
123
  end
116
124
  to_symbol == :to ? result : !result
117
125
  end
@@ -233,7 +241,6 @@ module RuboCop
233
241
  corrector.insert_after(actual, ".#{predicate}" + args + block)
234
242
  end
235
243
 
236
- # rubocop:disable Metrics/MethodLength
237
244
  def to_predicate_method(matcher)
238
245
  case matcher = matcher.to_s
239
246
  when 'be_a', 'be_an', 'be_a_kind_of', 'a_kind_of', 'be_kind_of'
@@ -250,7 +257,6 @@ module RuboCop
250
257
  "#{matcher[/\Abe_(.+)/, 1]}?"
251
258
  end
252
259
  end
253
- # rubocop:enable Metrics/MethodLength
254
260
 
255
261
  def replacement_matcher(node)
256
262
  case [cop_config['Strict'], node.method?(:to)]
@@ -260,7 +266,7 @@ module RuboCop
260
266
  'be(false)'
261
267
  when [false, true]
262
268
  'be_truthy'
263
- when [false, false]
269
+ else
264
270
  'be_falsey'
265
271
  end
266
272
  end
@@ -329,6 +335,10 @@ module RuboCop
329
335
  check_inflected(node)
330
336
  when :explicit
331
337
  check_explicit(node)
338
+ else
339
+ # :nocov:
340
+ :noop
341
+ # :nocov:
332
342
  end
333
343
  end
334
344
 
@@ -80,10 +80,10 @@ module RuboCop
80
80
 
81
81
  def check_block_body(block)
82
82
  body = block.body
83
- unless dynamic?(body) # rubocop:disable Style/GuardClause
84
- add_offense(block.loc.begin, message: MSG_AND_RETURN) do |corrector|
85
- BlockBodyCorrector.new(block).call(corrector)
86
- end
83
+ return if dynamic?(body)
84
+
85
+ add_offense(block.loc.begin, message: MSG_AND_RETURN) do |corrector|
86
+ BlockBodyCorrector.new(block).call(corrector)
87
87
  end
88
88
  end
89
89
 
@@ -162,6 +162,7 @@ module RuboCop
162
162
  end
163
163
 
164
164
  NULL_BLOCK_BODY = Struct.new(:loc, :source).new(nil, 'nil')
165
+ private_constant :NULL_BLOCK_BODY
165
166
  end
166
167
  end
167
168
  end
@@ -6,9 +6,7 @@ module RuboCop
6
6
  module RSpec
7
7
  # Builds a YAML config file from two config hashes
8
8
  class ConfigFormatter
9
- EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
10
- SUBDEPARTMENTS = [].freeze
11
- AMENDMENTS = %(Metrics/BlockLength)
9
+ EXTENSION_ROOT_DEPARTMENT = %r{^RSpec/}.freeze
12
10
  COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
13
11
 
14
12
  def initialize(config, descriptions)
@@ -18,18 +16,15 @@ module RuboCop
18
16
 
19
17
  def dump
20
18
  YAML.dump(unified_config)
21
- .gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
22
- .gsub(*AMENDMENTS, "\n\\0")
23
- .gsub(/^(\s+)- /, '\1 - ')
24
- .gsub('"~"', '~')
19
+ .gsub(%r{^\w+/}, "\n\\0") # Add an extra newline before each cop.
20
+ .gsub(/^(\s+)- /, '\1 - ') # Add 2 spaces before each array element.
21
+ .gsub('"~"', '~') # Don't quote tilde, YAML's null value.
25
22
  end
26
23
 
27
24
  private
28
25
 
29
26
  def unified_config
30
27
  cops.each_with_object(config.dup) do |cop, unified|
31
- next if SUBDEPARTMENTS.include?(cop) || AMENDMENTS.include?(cop)
32
-
33
28
  replace_nil(unified[cop])
34
29
  unified[cop].merge!(descriptions.fetch(cop))
35
30
  unified[cop]['Reference'] = reference(cop)
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lint_roller'
4
+
5
+ module RuboCop
6
+ module RSpec
7
+ # A plugin that integrates RuboCop RSpec with RuboCop's plugin system.
8
+ class Plugin < LintRoller::Plugin
9
+ # :nocov:
10
+ def about
11
+ LintRoller::About.new(
12
+ name: 'rubocop-rspec',
13
+ version: Version::STRING,
14
+ homepage: 'https://github.com/rubocop/rubocop-rspec',
15
+ description: 'Code style checking for RSpec files.'
16
+ )
17
+ end
18
+ # :nocov:
19
+
20
+ def supported?(context)
21
+ context.engine == :rubocop
22
+ end
23
+
24
+ def rules(_context)
25
+ project_root = Pathname.new(__dir__).join('../../..')
26
+
27
+ ConfigObsoletion.files << project_root.join('config', 'obsoletion.yml')
28
+
29
+ LintRoller::Rules.new(
30
+ type: :path,
31
+ config_format: :rubocop,
32
+ value: project_root.join('config/default.yml')
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Version information for the RSpec RuboCop plugin.
6
6
  module Version
7
- STRING = '3.4.0'
7
+ STRING = '3.5.0'
8
8
  end
9
9
  end
10
10
  end
@@ -17,7 +17,6 @@ module RuboCop
17
17
  @replacements = replace
18
18
  end
19
19
 
20
- # rubocop:disable Metrics/MethodLength
21
20
  def rewrite
22
21
  case text
23
22
  when SHOULDNT_BE_PREFIX
@@ -32,7 +31,6 @@ module RuboCop
32
31
  remove_should_and_pluralize
33
32
  end
34
33
  end
35
- # rubocop:enable Metrics/MethodLength
36
34
 
37
35
  private
38
36
 
data/lib/rubocop/rspec.rb CHANGED
@@ -3,12 +3,5 @@
3
3
  module RuboCop
4
4
  # RuboCop RSpec project namespace
5
5
  module RSpec
6
- PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
7
- CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
8
-
9
- private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
10
-
11
- ::RuboCop::ConfigObsoletion.files << PROJECT_ROOT.join('config',
12
- 'obsoletion.yml')
13
6
  end
14
7
  end
data/lib/rubocop-rspec.rb CHANGED
@@ -6,9 +6,9 @@ require 'yaml'
6
6
  require 'rubocop'
7
7
 
8
8
  require_relative 'rubocop/rspec'
9
- require_relative 'rubocop/rspec/inject'
10
9
  require_relative 'rubocop/rspec/language'
11
10
  require_relative 'rubocop/rspec/node'
11
+ require_relative 'rubocop/rspec/plugin'
12
12
  require_relative 'rubocop/rspec/version'
13
13
  require_relative 'rubocop/rspec/wording'
14
14
 
@@ -34,8 +34,6 @@ require_relative 'rubocop/rspec/example'
34
34
  require_relative 'rubocop/rspec/example_group'
35
35
  require_relative 'rubocop/rspec/hook'
36
36
 
37
- RuboCop::RSpec::Inject.defaults!
38
-
39
37
  require_relative 'rubocop/cop/rspec_cops'
40
38
 
41
39
  # We have to register our autocorrect incompatibilities in RuboCop's cops
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.0
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Backus
@@ -9,22 +9,42 @@ authors:
9
9
  - Nils Gemeinhardt
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-01-20 00:00:00.000000000 Z
12
+ date: 2025-02-16 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: lint_roller
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.1'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: rubocop
16
30
  requirement: !ruby/object:Gem::Requirement
17
31
  requirements:
18
32
  - - "~>"
19
33
  - !ruby/object:Gem::Version
20
- version: '1.61'
34
+ version: '1.72'
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: 1.72.1
21
38
  type: :runtime
22
39
  prerelease: false
23
40
  version_requirements: !ruby/object:Gem::Requirement
24
41
  requirements:
25
42
  - - "~>"
26
43
  - !ruby/object:Gem::Version
27
- version: '1.61'
44
+ version: '1.72'
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.72.1
28
48
  description: |
29
49
  Code style checking for RSpec files.
30
50
  A plugin for the RuboCop code style enforcing & linting tool.
@@ -178,9 +198,9 @@ files:
178
198
  - lib/rubocop/rspec/example.rb
179
199
  - lib/rubocop/rspec/example_group.rb
180
200
  - lib/rubocop/rspec/hook.rb
181
- - lib/rubocop/rspec/inject.rb
182
201
  - lib/rubocop/rspec/language.rb
183
202
  - lib/rubocop/rspec/node.rb
203
+ - lib/rubocop/rspec/plugin.rb
184
204
  - lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb
185
205
  - lib/rubocop/rspec/version.rb
186
206
  - lib/rubocop/rspec/wording.rb
@@ -191,6 +211,7 @@ metadata:
191
211
  changelog_uri: https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md
192
212
  documentation_uri: https://docs.rubocop.org/rubocop-rspec/
193
213
  rubygems_mfa_required: 'true'
214
+ default_lint_roller_plugin: RuboCop::RSpec::Plugin
194
215
  rdoc_options: []
195
216
  require_paths:
196
217
  - lib
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module RSpec
5
- # Because RuboCop doesn't yet support plugins, we have to monkey patch in a
6
- # bit of our configuration.
7
- module Inject
8
- def self.defaults!
9
- path = CONFIG_DEFAULT.to_s
10
- hash = ConfigLoader.send(:load_yaml_configuration, path)
11
- config = RuboCop::Config.new(hash, path)
12
- puts "configuration from #{path}" if ConfigLoader.debug?
13
- config = ConfigLoader.merge_with_default(config, path)
14
- ConfigLoader.instance_variable_set(:@default_configuration, config)
15
- end
16
- end
17
- end
18
- end