Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layout/ArgumentAlignment and Layout/FirstHashElementIndentation cops are incompatible #9811

Closed
laserlemon opened this issue May 18, 2021 · 0 comments · Fixed by #9812
Closed
Labels

Comments

@laserlemon
Copy link

After upgrading rubocop from version 1.14.0 to 1.15.0, I started seeing new, auto-correctable offenses. But when trying to auto-correct, two of my configurations collide in such a way as to prevent auto-correction because of an infinite loop of back-and-forth corrections. I've tried to build a simple example to demonstrate the issue below. Thank you! 💛


Expected behavior

It seems to me that the Layout/ArgumentAlignment cop is behaving unexpectedly when:

  1. Configured with_fixed_indentation
  2. Analyzing a multiline method call containing a multiline hash as an argument

To make matters more interesting, the Layout/FirstHashElementIndentation cop will try to correct the Layout/ArgumentAlignment cop's bad behavior, resulting in an infinite loop.

Given the following Rubocop configuration:

Layout/ArgumentAlignment:
  Enabled: true
  EnforcedStyle: with_fixed_indentation

and the following Ruby:

# frozen_string_literal: true

my_method(
  {
    foo: 'bar',
    baz: 'qux'
  }
)

I expect no offenses when I run:

$ rubocop --debug --config .rubocop_test.yml test.rb

    💭
🤔 Note: You might think that I should change my Ruby to something like:

# frozen_string_literal: true

my_method({
  foo: 'bar',
  baz: 'qux'
})

and I might agree in a single-argument case but this is also an issue with multiple arguments as you might see in testing:

# frozen_string_literal: true

assert_equal(
  {
    expected: 'values',
    more: 'values'
  },
  my_object.actual_values
)

Actual behavior

Instead of seeing no offenses, I see the following output:

configuration from /Users/laserlemon/Code/rubocop-test/.rubocop_test.yml
Default configuration from /Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/config/default.yml
Inspecting 1 file
Scanning /Users/laserlemon/Code/rubocop-test/test.rb
Loading cache from /Users/laserlemon/.cache/rubocop_cache/2f6606865fb80e34d8545ab577ef9079910d5f83/19abaaa4823a9db9a9eb0469867cd4c7524024e5/b730d40270a7b3927de5bbb0d0e896a2b216f86b
C

Offenses:

test.rb:5:5: C: [Correctable] Layout/ArgumentAlignment: Use one level of indentation for arguments following the first line of a multi-line method call.
    foo: 'bar',
    ^^^^^^^^^^
test.rb:6:5: C: [Correctable] Layout/ArgumentAlignment: Use one level of indentation for arguments following the first line of a multi-line method call.
    baz: 'qux'
    ^^^^^^^^^^

1 file inspected, 2 offenses detected, 2 offenses auto-correctable
Finished in 0.12812699936330318 seconds

And if I try to auto-correct the offenses with:

$ rubocop --debug --auto-correct --config .rubocop_test.yml test.rb

I see:

configuration from /Users/laserlemon/Code/rubocop-test/.rubocop_test.yml
Default configuration from /Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/config/default.yml
Inspecting 1 file
Scanning /Users/laserlemon/Code/rubocop-test/test.rb
C

Offenses:

test.rb:5:3: C: [Corrected] Layout/FirstHashElementIndentation: Use 2 spaces for indentation in a hash, relative to the start of the line where the left curly brace is.
  foo: 'bar',
  ^^^^^^^^^^
test.rb:5:5: C: [Corrected] Layout/ArgumentAlignment: Use one level of indentation for arguments following the first line of a multi-line method call.
    foo: 'bar',
    ^^^^^^^^^^
test.rb:6:5: C: [Corrected] Layout/ArgumentAlignment: Use one level of indentation for arguments following the first line of a multi-line method call.
    baz: 'qux'
    ^^^^^^^^^^

0 files inspected, 3 offenses detected, 3 offenses corrected
Infinite loop detected in /Users/laserlemon/Code/rubocop-test/test.rb and caused by Layout/FirstHashElementIndentation -> Layout/ArgumentAlignment
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:299:in `check_for_infinite_loop'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:282:in `block in iterate_until_no_changes'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:281:in `loop'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:281:in `iterate_until_no_changes'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:250:in `do_inspection_loop'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:130:in `block in file_offenses'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:155:in `file_offense_cache'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:129:in `file_offenses'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:120:in `process_file'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:101:in `block in each_inspected_file'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:100:in `each'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:100:in `reduce'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:100:in `each_inspected_file'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:86:in `inspect_files'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/runner.rb:47:in `run'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli/command/execute_runner.rb:26:in `block in execute_runner'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli/command/execute_runner.rb:52:in `with_redirect'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli/command/execute_runner.rb:25:in `execute_runner'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli/command/execute_runner.rb:17:in `run'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli/command.rb:11:in `run'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli/environment.rb:18:in `run'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli.rb:65:in `run_command'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli.rb:72:in `execute_runners'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/lib/rubocop/cli.rb:41:in `run'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/exe/rubocop:12:in `block in <top (required)>'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/2.7.0/benchmark.rb:308:in `realtime'
/Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/exe/rubocop:12:in `<top (required)>'
/Users/laserlemon/.rbenv/versions/2.7.2/bin/rubocop:23:in `load'
/Users/laserlemon/.rbenv/versions/2.7.2/bin/rubocop:23:in `<main>'
Finished in 0.2105459999293089 seconds

If I disable Layout/FirstHashElementIndentation, I can see Layout/ArgumentAlignment's strange attempted behavior. Changing the Rubocop configuration to:

Layout/ArgumentAlignment:
  Enabled: true
  EnforcedStyle: with_fixed_indentation

Layout/FirstHashElementIndentation:
  Enabled: false

and running:

$ rubocop --debug --auto-correct --config .rubocop_test.yml test.rb

produces the following output:

configuration from /Users/laserlemon/Code/rubocop-test/.rubocop_test.yml
Default configuration from /Users/laserlemon/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rubocop-1.15.0/config/default.yml
Inspecting 1 file
Scanning /Users/laserlemon/Code/rubocop-test/test.rb
C

Offenses:

test.rb:5:5: C: [Corrected] Layout/ArgumentAlignment: Use one level of indentation for arguments following the first line of a multi-line method call.
    foo: 'bar',
    ^^^^^^^^^^
test.rb:6:5: C: [Corrected] Layout/ArgumentAlignment: Use one level of indentation for arguments following the first line of a multi-line method call.
    baz: 'qux'
    ^^^^^^^^^^

1 file inspected, 2 offenses detected, 2 offenses corrected
Finished in 0.18413299974054098 seconds

and the following "corrected" Ruby:

# frozen_string_literal: true

my_method(
  {
  foo: 'bar',
  baz: 'qux'
  }
)

Steps to reproduce the problem

See above! 😄

RuboCop version

$ rubocop -V
1.15.0 (using Parser 3.0.1.1, rubocop-ast 1.5.0, running on ruby 2.7.2 x86_64-darwin19)
@koic koic added the bug label May 18, 2021
koic added a commit to koic/rubocop that referenced this issue May 19, 2021
Fixes rubocop#9811.

This PR fixes an error for `Layout/ArgumentAlignment` with
`Layout/FirstHashElementIndentation` when setting
`EnforcedStyle: with_fixed_indentation`.
koic added a commit that referenced this issue May 22, 2021
…lignment

[Fix #9811] Fix an error for `Layout/ArgumentAlignment`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants