Skip to content

Commit

Permalink
Fix inherit_mode for arrays in extension default
Browse files Browse the repository at this point in the history
See rubocop/rubocop-rspec#1126

`config/default.yml`:
```yaml
RSpec:
  Language:
    Examples:
      inherit_mode:
        merge:
          - Regular
      Regular:
        - it
        - specify
        - example
        - scenario
        - its
```

`.rubocop.yml`:
```yaml
require:
  - rubocop-rspec

RSpec:
  Language:
    Examples:
      Regular:
        - mycustomexamplealias
```

Previously, locally-set `inherit_mode` in extension default
configuration was not respected.
  • Loading branch information
pirj committed Aug 3, 2021
1 parent b5f3438 commit 22a1397
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 6 deletions.
1 change: 1 addition & 0 deletions changelog/fix_inherit_mode-for-extensions.md
@@ -0,0 +1 @@
* [#9952](https://github.com/rubocop/rubocop/pull/9952) [rubocop-rspec#1126](https://github.com/rubocop/rubocop-rspec/issues/1126): Fix `inherit_mode` for deeply nested configuration defined in extensions' default configuration. ([@pirj][])
27 changes: 21 additions & 6 deletions lib/rubocop/config_loader_resolver.rb
Expand Up @@ -108,7 +108,7 @@ def merge(base_hash, derived_hash, **opts)
result.delete(key)
elsif merge_hashes?(base_hash, derived_hash, key)
result[key] = merge(base_hash[key], derived_hash[key], **opts)
elsif should_union?(base_hash, key, opts[:inherit_mode])
elsif should_union?(derived_hash, base_hash, opts[:inherit_mode], key)
result[key] = base_hash[key] | derived_hash[key]
elsif opts[:debug]
warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
Expand Down Expand Up @@ -183,11 +183,26 @@ def determine_inherit_mode(hash, key)
local_inherit || hash['inherit_mode'] || {}
end

def should_union?(base_hash, key, inherit_mode)
base_hash[key].is_a?(Array) &&
inherit_mode &&
inherit_mode['merge'] &&
inherit_mode['merge'].include?(key)
def should_union?(derived_hash, base_hash, root_mode, key)
return false unless base_hash[key].is_a?(Array)

derived_mode = derived_hash['inherit_mode']
return false if should_override?(derived_mode, key)
return true if should_merge?(derived_mode, key)

base_mode = base_hash['inherit_mode']
return false if should_override?(base_mode, key)
return true if should_merge?(base_mode, key)

should_merge?(root_mode, key)
end

def should_merge?(mode, key)
mode && mode['merge'] && mode['merge'].include?(key)
end

def should_override?(mode, key)
mode && mode['override'] && mode['override'].include?(key)
end

def merge_hashes?(base_hash, derived_hash, key)
Expand Down
53 changes: 53 additions & 0 deletions spec/rubocop/config_loader_spec.rb
Expand Up @@ -537,6 +537,59 @@
end
end

context 'when inherit_mode is specified for a nested element even ' \
'without explicitly specifying `inherit_from`/`inherit_gem`' do
let(:file_path) { '.rubocop.yml' }

before do
stub_const('RuboCop::ConfigLoader::RUBOCOP_HOME', 'rubocop')
stub_const('RuboCop::ConfigLoader::DEFAULT_FILE',
File.join('rubocop', 'config', 'default.yml'))

create_file('rubocop/config/default.yml', <<~YAML)
Language:
Examples:
inherit_mode:
merge:
- Regular
- Focused
Regular:
- it
Focused:
- fit
Skipped:
- xit
Pending:
- pending
YAML
create_file(file_path, <<~YAML)
Language:
Examples:
inherit_mode:
merge:
- Skipped
override:
- Focused
Regular:
- scenario
Focused:
- fscenario
Skipped:
- xscenario
Pending:
- later
YAML
end

it 'respects the priority of `inherit_mode`, user-defined first' do
examples_configuration = configuration_from_file['Language']['Examples']
expect(examples_configuration['Regular']).to contain_exactly('it', 'scenario')
expect(examples_configuration['Focused']).to contain_exactly('fscenario')
expect(examples_configuration['Skipped']).to contain_exactly('xit', 'xscenario')
expect(examples_configuration['Pending']).to contain_exactly('later')
end
end

context 'when a department is disabled', :restore_registry do
let(:file_path) { '.rubocop.yml' }

Expand Down

0 comments on commit 22a1397

Please sign in to comment.