rubocop-rspec 3.4.0 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
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