Skip to content

Commit

Permalink
[Fix #12667] Avoid loading excluded configuration
Browse files Browse the repository at this point in the history
This change fixes an error that can occur when file names are
given explicitly on the command line together with
`--force-exclusion`.

In order to check if the given files are to be excluded, we
must load configuration. The problem is that `.rubocop.yml`
files in directories with excluded files (e.g. a `vendor`
directory) might contain directives that will cause RuboCop
to crash, such as `require` with an extension that's not
available.

What saves us in this situation is that we don't need to
load configuration for the file as such. We can load
configuration for the current directory instead. The reason
is that `Exclude` parameters on the top level are not
shadowed by `Exclude` in other `.rubocop.yml` files in
subdirectories, as documented here:

https://docs.rubocop.org/rubocop/1.60/configuration.html#include-and-exclude-are-relative-to-their-directory

The `--ignore-parent-exclusion` flag, if given, changes the
situation and we must load the most adjacent `.rubocop.yml`
file.
  • Loading branch information
jonas054 authored and bbatsov committed Mar 4, 2024
1 parent 45cc74e commit 664ba3d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog/fix_loading_of_excluded_config.md
@@ -0,0 +1 @@
* [#12667](https://github.com/rubocop/rubocop/issues/12667): Don't load excluded configuration. ([@jonas054][])
12 changes: 10 additions & 2 deletions lib/rubocop/target_finder.rb
Expand Up @@ -16,6 +16,10 @@ def force_exclusion?
@options[:force_exclusion]
end

def ignore_parent_exclusion?
@options[:ignore_parent_exclusion]
end

def debug?
@options[:debug]
end
Expand Down Expand Up @@ -181,7 +185,7 @@ def included_file?(file)
ruby_file?(file) || configured_include?(file)
end

def process_explicit_path(path, mode)
def process_explicit_path(path, mode) # rubocop:disable Metrics/CyclomaticComplexity
files = path.include?('*') ? Dir[path] : [path]

if mode == :only_recognized_file_types || force_exclusion?
Expand All @@ -191,7 +195,11 @@ def process_explicit_path(path, mode)
return files unless force_exclusion?

files.reject do |file|
config = @config_store.for(file)
# When --ignore-parent-exclusion is given, we must look at the configuration associated with
# the file, but in the default case when --ignore-parent-exclusion is not given, can safely
# look only at the configuration for the current directory, since it's only the Exclude
# parameters we're going to check.
config = @config_store.for(ignore_parent_exclusion? ? file : '.')
config.file_to_exclude?(file)
end
end
Expand Down
31 changes: 28 additions & 3 deletions spec/rubocop/target_finder_spec.rb
Expand Up @@ -62,8 +62,15 @@
subject(:target_finder) { described_class.new(config_store, options) }

let(:config_store) { RuboCop::ConfigStore.new }
let(:options) { { force_exclusion: force_exclusion, debug: debug } }
let(:options) do
{
force_exclusion: force_exclusion,
ignore_parent_exclusion: ignore_parent_exclusion,
debug: debug
}
end
let(:force_exclusion) { false }
let(:ignore_parent_exclusion) { false }
let(:debug) { false }

before do
Expand Down Expand Up @@ -144,8 +151,26 @@
context "when it's forced to adhere file exclusion configuration" do
let(:force_exclusion) { true }

it 'excludes them' do
expect(found_basenames).to eq(['ruby2.rb'])
context 'when parent exclusion is in effect' do
before do
create_file('dir2/.rubocop.yml', <<~YAML)
require:
- unloadable_extension
YAML
end

it 'excludes only files that are excluded on top level and does not load ' \
'other configuration files unnecessarily' do
expect(found_basenames).to eq(['ruby2.rb', 'executable'])
end
end

context 'when parent exclusion is ignored' do
let(:ignore_parent_exclusion) { true }

it 'excludes files that are excluded on any level' do
expect(found_basenames).to eq(['ruby2.rb'])
end
end
end
end
Expand Down

0 comments on commit 664ba3d

Please sign in to comment.