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
Break long method definitions when auto-correcting #10692
Conversation
05b0523
to
9898145
Compare
@@ -216,6 +218,8 @@ def process_args(args) | |||
|
|||
# @api private | |||
def already_on_multiple_lines?(node) | |||
return node.first_line != node.arguments.last.last_line if node.def_type? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed as node.last_line
returns the line where the end
keyword is. Maybe there is a better approach here, the downside of the approach I chose is that:
def foo(bar, bat
)
end
Does get wrapped on multiple lines. That's not strictly a bad behaviour as this only triggers when the line is longer then the maximum length, but still somewhat unexpected.
I've run this feature locally and infinite loop is detected on 98981457abc38c3edd1f6a2a738f144314fedd0a. # .rubocop.yml
AllCops:
NewCops: enable
TargetRubyVersion: 3.1
Layout/LineLength:
Max: 40 # example.rb
def foo(abc: '100000', def: '100000', ghi: '100000', jkl: '100000', mno: '100000'); end $ bundle exec rubocop -a example.rb
Inspecting 1 file
W
Offenses:
example.rb:1:1: C: [Corrected] Style/EmptyMethod: Put empty method definitions on a single line.
def foo(abc: '100000', def: '100000', ghi: '100000', jkl: '100000', mno: '100000'); ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
example.rb:1:38: C: [Corrected] Layout/TrailingWhitespace: Trailing whitespace detected.
def foo(abc: '100000', def: '100000',
^
example.rb:1:41: C: [Corrected] Layout/LineLength: Line is too long. [83/40]
def foo(abc: '100000', def: '100000', ghi: '100000', jkl: '100000', mno: '100000');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
example.rb:1:41: C: [Corrected] Layout/LineLength: Line is too long. [87/40]
def foo(abc: '100000', def: '100000', ghi: '100000', jkl: '100000', mno: '100000'); end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
example.rb:1:83: C: [Corrected] Style/Semicolon: Do not use semicolons to terminate expressions.
def foo(abc: '100000', def: '100000', ghi: '100000', jkl: '100000', mno: '100000');
^
example.rb:2:1: C: [Corrected] Layout/ParameterAlignment: Align the parameters of a method definition if they span more than one line.
ghi: '100000', jkl: '100000', mno: '100000')
^^^^^^^^^^^^^
example.rb:2:2: W: [Corrected] Layout/DefEndAlignment: end at 2, 1 is not aligned with def at 1, 0.
end
^^^
example.rb:2:41: C: Layout/LineLength: Line is too long. [52/40]
ghi: '100000', jkl: '100000', mno: '100000')
^^^^^^^^^^^^
0 files inspected, 8 offenses detected, 7 offenses corrected
Infinite loop detected in /Users/nobuyo/dev/rubocop-test/example.rb and caused by Layout/LineLength -> Layout/DefEndAlignment, Layout/LineLength, Style/EmptyMethod, Style/Semicolon -> Layout/ParameterAlignment, Layout/TrailingWhitespace, Style/EmptyMethod -> Layout/LineLength, Style/EmptyMethod
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:296:in `check_for_infinite_loop'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:279:in `block in iterate_until_no_changes'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:278:in `loop'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:278:in `iterate_until_no_changes'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:247:in `do_inspection_loop'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:130:in `block in file_offenses'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:155:in `file_offense_cache'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:129:in `file_offenses'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:120:in `process_file'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:101:in `block in each_inspected_file'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:100:in `each'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:100:in `reduce'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:100:in `each_inspected_file'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:86:in `inspect_files'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/runner.rb:47:in `run'
/Users/nobuyo/dev/rubocop-korri/lib/rubocop/cli/command/execute_runner.rb:26:in `block in execute_runner'
# ... |
@nobuyo Looks like you example is already an infinite loop on the Using the # .rubocop.yml
AllCops:
NewCops: enable
TargetRubyVersion: 3.1
Layout/LineLength:
Max: 40
Style/EmptyMethod:
EnforcedStyle: expanded # example.rb (after autocorrect)
def foo(abc: '100000', def: '100000',
ghi: '100000', jkl: '100000', mno: '100000')
end |
Oh I see, thank you! |
Sorry if not relevant, this PR is pretty short and laconic, just like a warning: I like configuration like this: Layout/FirstArgumentIndentation:
EnforcedStyle: consistent
Layout/FirstParameterIndentation:
EnforcedStyle: consistent
Layout/FirstArrayElementIndentation:
EnforcedStyle: consistent
Layout/FirstHashElementIndentation:
EnforcedStyle: consistent
Layout/MultilineMethodCallIndentation:
EnforcedStyle: indented
Layout/MultilineOperationIndentation:
EnforcedStyle: indented
Layout/MultilineArrayBraceLayout:
EnforcedStyle: new_line
Layout/MultilineHashBraceLayout:
EnforcedStyle: new_line
Layout/ArgumentAlignment:
EnforcedStyle: with_fixed_indentation
Layout/ParameterAlignment:
EnforcedStyle: with_fixed_indentation And I'd like to see correct… style of breaking, I mean new lines instead of alignment. I hope this is already works correctly, maybe just we should add more specs for it. |
Not sure what you are concerned about (as in not sure I understand)? The change here is so that LineLength can wrap the method definition on it's own. |
I mean you have specs like this: expect_correction(<<~RUBY)
def foo(abc: "100000", def: "100000",#{trailing_whitespace}
ghi: "100000", jkl: "100000", mno: "100000")
end
RUBY And probably there should be additional context with another style of expect_correction(<<~RUBY)
def foo(
abc: "100000", def: "100000",#{trailing_whitespace}
ghi: "100000", jkl: "100000", mno: "100000")
end
RUBY
I'm discussing this small PR, and description and specs what I've seen. I'm not sure about (draft and large) 10691, maybe there it's resolved, but, again, I'm talking just about this PR and maybe I'm wrong. So, that's why I wrote from the start: "may be non-relevant and it's just a warning". I hope it's more understandable now. |
@AlexWayfer I think what you are describing is # .rubocop.yml
AllCops:
NewCops: enable
TargetRubyVersion: 3.1
Layout/LineLength:
Max: 40
Style/EmptyMethod:
EnforcedStyle: expanded
Layout/FirstParameterIndentation:
EnforcedStyle: consistent
Layout/ParameterAlignment:
EnforcedStyle: with_fixed_indentation
Layout/FirstMethodParameterLineBreak:
Enabled: true # source (bad)
# frozen_string_literal: true
def foo(abc: '100000', def: '100000', ghi: '100000', jkl: '100000', mno: '100000')
end # result (good)
# frozen_string_literal: true
def foo(
abc: '100000', def: '100000',
ghi: '100000', jkl: '100000', mno: '100000'
)
end (If you run the same example on the The goal of the change here, is just for As for specs, as far as I have seen, the codebase does not have specs for combined rules! |
This allows rubocop to autocorrect method definitions by wrapping them on multiple lines when they violate the `Layout/LineLength` rule by adding method definition logic inside `CheckLineBreakable`.
9898145
to
c06ff54
Compare
@bbatsov for context |
Looks good. Sorry for the slow turnaround here! |
Add autocorrect capabilities to
Layout/LineLength
, by wrapping method definitions on multiple lines.Combined with #10691 it allows for some nice autocorrect.
This was split from the larger WIP pull request here: #10681
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).bundle exec rake default
. It executes all tests and runs RuboCop on its own code.{change_type}_{change_description}.md
if the new code introduces user-observable changes. See changelog entry format for details.