Skip to content

Commit d95a384

Browse files
dvandersluisbbatsov
authored andcommitted
[Fix #9196] Fix ConfigObsoletion::ExtractedCop raising errors for loaded features when bundler is not activated.
1 parent 905e363 commit d95a384

File tree

4 files changed

+67
-32
lines changed

4 files changed

+67
-32
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#9196](https://github.com/rubocop-hq/rubocop/issues/9196): Fix `ConfigObsoletion::ExtractedCop` raising errors for loaded features when bundler is not activated. ([@dvandersluis][])

lib/rubocop/config_obsoletion/extracted_cop.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,29 @@ def initialize(config, old_name, gem)
1515
end
1616

1717
def violated?
18-
return false if gem_installed?
18+
return false if feature_loaded?
1919

20-
affected_gems.any?
20+
affected_cops.any?
2121
end
2222

2323
def rule_message
2424
msg = '%<name>s been extracted to the `%<gem>s` gem.'
2525
format(msg,
26-
name: affected_gems.size > 1 ? "`#{department}` cops have" : "`#{old_name}` has",
26+
name: affected_cops.size > 1 ? "`#{department}` cops have" : "`#{old_name}` has",
2727
gem: gem)
2828
end
2929

3030
private
3131

32-
def affected_gems
32+
def affected_cops
3333
return old_name unless old_name.end_with?('*')
3434

3535
# Handle whole departments (expressed as `Department/*`)
3636
config.keys.grep(Regexp.new("^#{department}"))
3737
end
3838

39-
def gem_installed?
40-
Lockfile.new.includes_gem?(gem)
39+
def feature_loaded?
40+
config.loaded_features.include?(gem)
4141
end
4242
end
4343
end

spec/rubocop/config_obsoletion_spec.rb

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
let(:configuration) { RuboCop::Config.new(hash, loaded_path) }
99
let(:loaded_path) { 'example/.rubocop.yml' }
10+
let(:requires) { [] }
11+
12+
before { allow(configuration).to receive(:loaded_features).and_return(requires) }
1013

1114
describe '#validate', :isolated_environment do
1215
context 'when the configuration includes any obsolete cop name' do
@@ -225,33 +228,16 @@
225228
}
226229
end
227230

228-
let(:expected_message) do
229-
<<~OUTPUT.chomp
230-
`Performance` cops have been extracted to the `rubocop-performance` gem.
231-
(obsolete configuration found in example/.rubocop.yml, please update it)
232-
`Rails` cops have been extracted to the `rubocop-rails` gem.
233-
(obsolete configuration found in example/.rubocop.yml, please update it)
234-
OUTPUT
235-
end
236-
237-
context 'when the gems are installed' do
238-
before do
239-
allow_any_instance_of(RuboCop::ConfigObsoletion::ExtractedCop)
240-
.to receive(:gem_installed?).and_return(true)
241-
end
231+
context 'when the extensions are loaded' do
232+
let(:requires) { %w[rubocop-rails rubocop-performance] }
242233

243234
it 'does not print a warning message' do
244235
expect { config_obsoletion.reject_obsolete! }.not_to raise_error
245236
end
246237
end
247238

248-
context 'when only one gem is installed' do
249-
before do
250-
allow_any_instance_of(RuboCop::Lockfile)
251-
.to receive(:includes_gem?).and_return(false)
252-
allow_any_instance_of(RuboCop::Lockfile)
253-
.to receive(:includes_gem?).with('rubocop-performance').and_return(true)
254-
end
239+
context 'when only one extension is loaded' do
240+
let(:requires) { %w[rubocop-performance] }
255241

256242
let(:expected_message) do
257243
<<~OUTPUT.chomp
@@ -270,10 +256,14 @@
270256
end
271257
end
272258

273-
context 'when the gems are not installed' do
274-
before do
275-
allow_any_instance_of(RuboCop::ConfigObsoletion::ExtractedCop)
276-
.to receive(:gem_installed?).and_return(false)
259+
context 'when the extensions are not loaded' do
260+
let(:expected_message) do
261+
<<~OUTPUT.chomp
262+
`Performance` cops have been extracted to the `rubocop-performance` gem.
263+
(obsolete configuration found in example/.rubocop.yml, please update it)
264+
`Rails` cops have been extracted to the `rubocop-rails` gem.
265+
(obsolete configuration found in example/.rubocop.yml, please update it)
266+
OUTPUT
277267
end
278268

279269
it 'prints a warning message' do
@@ -285,11 +275,50 @@
285275
end
286276
end
287277
end
278+
279+
context 'when the extensions are loaded via inherit_gem' do
280+
let(:resolver) { RuboCop::ConfigLoaderResolver.new }
281+
let(:gem_root) { File.expand_path('gems') }
282+
283+
let(:hash) do
284+
{
285+
'inherit_gem' => { 'rubocop-includes' => '.rubocop.yml' },
286+
'Performance/Casecmp' => { 'Enabled': true }
287+
}
288+
end
289+
290+
around do |example|
291+
RuboCop::Cop::Registry.with_temporary_global(RuboCop::Cop::Registry.new) { example.run }
292+
end
293+
294+
before do
295+
create_file("#{gem_root}/rubocop-includes/.rubocop.yml", <<~YAML)
296+
require:
297+
- rubocop-performance
298+
YAML
299+
300+
# Mock out a gem in order to test `inherit_gem`.
301+
gem_class = Struct.new(:gem_dir)
302+
mock_spec = gem_class.new(File.join(gem_root, 'rubocop-includes'))
303+
allow(Gem::Specification).to receive(:find_by_name)
304+
.with('rubocop-includes').and_return(mock_spec)
305+
306+
# Resolve `inherit_gem`
307+
resolver.resolve_inheritance_from_gems(hash)
308+
resolver.resolve_inheritance(loaded_path, hash, loaded_path, false)
309+
310+
allow(configuration).to receive(:loaded_features).and_call_original
311+
end
312+
313+
it 'does not raise a ValidationError' do
314+
expect { config_obsoletion.reject_obsolete! }.not_to raise_error
315+
end
316+
end
288317
end
289318

290319
context 'when the configuration includes any obsolete parameters' do
291320
before do
292-
allow_any_instance_of(RuboCop::Lockfile).to receive(:includes_gem?).and_return(true)
321+
allow(configuration).to receive(:loaded_features).and_return(%w[rubocop-rails])
293322
end
294323

295324
let(:hash) do

spec/rubocop/cop/generator_spec.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,11 @@ def on_send(node)
334334
let(:options) { { formatters: [] } }
335335
let(:runner) { RuboCop::Runner.new(options, config) }
336336

337+
before do
338+
# Ignore any config validation errors
339+
allow_any_instance_of(RuboCop::ConfigValidator).to receive(:validate) # rubocop:disable RSpec/AnyInstance
340+
end
341+
337342
it 'generates a cop file that has no offense' do
338343
generator.write_source
339344
expect(runner.run([])).to be true

0 commit comments

Comments
 (0)