diff --git a/CHANGELOG.md b/CHANGELOG.md index 098044809fb..7451acd341f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +* [#8347](https://github.com/rubocop-hq/rubocop/issues/8347): Fix creating syntax errors when combining `Layout/HashAlignment` with `Style/HashSyntax` set to `hash_rockets`. ([@dorner][]) + ### Bug fixes * [#8324](https://github.com/rubocop-hq/rubocop/issues/8324): Fix crash for `Layout/SpaceAroundMethodCallOperator` when using `Proc#call` shorthand syntax. ([@fatkodima][]) diff --git a/lib/rubocop/cop/style/hash_syntax.rb b/lib/rubocop/cop/style/hash_syntax.rb index 65d6fbf661d..e52d98b69b7 100644 --- a/lib/rubocop/cop/style/hash_syntax.rb +++ b/lib/rubocop/cop/style/hash_syntax.rb @@ -199,7 +199,7 @@ def argument_without_space?(node) def autocorrect_hash_rockets(corrector, pair_node) op = pair_node.loc.operator - corrector.wrap(pair_node.key, ':', pair_node.inverse_delimiter(true)) + corrector.replace(pair_node.key, ":#{pair_node.key.source}#{pair_node.inverse_delimiter(true)}") corrector.remove(range_with_surrounding_space(range: op)) end diff --git a/lib/rubocop/rspec/cop_helper.rb b/lib/rubocop/rspec/cop_helper.rb index fd357554cff..be92b632fc1 100644 --- a/lib/rubocop/rspec/cop_helper.rb +++ b/lib/rubocop/rspec/cop_helper.rb @@ -46,10 +46,12 @@ def autocorrect_source(source, file = nil) @last_corrector.rewrite end - def _investigate(cop, processed_source) - team = RuboCop::Cop::Team.new([cop], nil, raise_error: true) + def _investigate(cops, processed_source) + cop_array = Array(cops) + team = RuboCop::Cop::Team.new(cop_array, nil, raise_error: true) report = team.investigate(processed_source) @last_corrector = report.correctors.first || RuboCop::Cop::Corrector.new(processed_source) + report.correctors[1..-1].each { |corr| @last_corrector.merge!(corr) if corr } report.offenses end end diff --git a/lib/rubocop/rspec/expect_offense.rb b/lib/rubocop/rspec/expect_offense.rb index b44eb1b664e..33b213f9d4c 100644 --- a/lib/rubocop/rspec/expect_offense.rb +++ b/lib/rubocop/rspec/expect_offense.rb @@ -130,7 +130,7 @@ def expect_offense(source, file = nil, severity: nil, **replacements) raise 'Error parsing example code' unless @processed_source.valid_syntax? - offenses = _investigate(cop, @processed_source) + offenses = _investigate(run_first_cops + [cop], @processed_source) actual_annotations = expected_annotations.with_offense_annotations(offenses) @@ -158,7 +158,7 @@ def expect_correction(correction, loop: true) # Prepare for next loop @processed_source = parse_source(corrected_source, @processed_source.path) - _investigate(cop, @processed_source) + _investigate(run_first_cops + [cop], @processed_source) end expect(new_source).to eq(correction) diff --git a/lib/rubocop/rspec/shared_contexts.rb b/lib/rubocop/rspec/shared_contexts.rb index b2bafec34c8..1f61bbc5551 100644 --- a/lib/rubocop/rspec/shared_contexts.rb +++ b/lib/rubocop/rspec/shared_contexts.rb @@ -58,6 +58,8 @@ let(:other_cops) { {} } + let(:run_first) { [] } + let(:cop_options) { {} } ### Utilities @@ -92,6 +94,15 @@ def source_range(range, buffer: source_buffer) let(:config) do hash = { 'AllCops' => all_cops_config, cop_class.cop_name => cur_cop_config }.merge!(other_cops) + run_first.each do |run_first_cop| + run_first_cop_config = RuboCop::ConfigLoader + .default_configuration.for_cop(run_first_cop) + .merge({ + 'Enabled' => true, # in case it is 'pending' + 'AutoCorrect' => true # in case defaults set it to false + }).merge(other_cops[run_first_cop.badge.to_s] || {}) + hash.merge!(run_first_cop.badge.to_s => run_first_cop_config) + end RuboCop::Config.new(hash, "#{Dir.pwd}/.rubocop.yml") end @@ -101,6 +112,15 @@ def source_range(range, buffer: source_buffer) cop.send :begin_investigation, processed_source end end + + let(:run_first_cops) do + run_first.map do |cop_class| + cop_class.new(config, cop_options).tap do |cop| + cop.send :begin_investigation, processed_source + end + end + end + end RSpec.shared_context 'mock console output' do diff --git a/spec/rubocop/cop/style/hash_syntax_spec.rb b/spec/rubocop/cop/style/hash_syntax_spec.rb index c06800ce0f6..7b47ecef7db 100644 --- a/spec/rubocop/cop/style/hash_syntax_spec.rb +++ b/spec/rubocop/cop/style/hash_syntax_spec.rb @@ -24,6 +24,15 @@ let(:cop_config_overrides) { {} } + let(:other_cops) do + { + 'Layout/HashAlignment' => { + 'EnforcedHashRocketStyle' => 'key', + 'EnforcedColonStyle' => 'key' + } + } + end + it 'registers offense for hash rocket syntax when new is possible' do expect_offense(<<~RUBY) x = { :a => 0 } @@ -331,6 +340,28 @@ it 'does not register an offense when there is a symbol value' do expect_no_offenses('{ :a => :b, :c => :d }') end + + context 'with Layout/HashAlignment' do + let(:run_first) { [RuboCop::Cop::Layout::HashAlignment] } + it 'should not conflict' do + expect_offense(<<~RUBY) +some_method(a: 'abc', b: 'abc', + ^^ Use hash rockets syntax. + ^^ Use hash rockets syntax. + c: 'abc', d: 'abc' + ^^ Use hash rockets syntax. + ^^ Use hash rockets syntax. + ^^^^^^^^ Align the keys of a hash literal if they span more than one line. + ) + RUBY + + expect_correction(<<~RUBY) +some_method(:a => 'abc', :b => 'abc', + :c => 'abc', :d => 'abc' + ) + RUBY + end + end end end @@ -650,4 +681,5 @@ expect(new_source).to eq('{ :a => 1, "b" => 2 }') end end + end