Skip to content

Commit

Permalink
Add line length autocorrect for blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Buildkite authored and bbatsov committed Feb 4, 2020
1 parent 8dd2894 commit ac65140
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -15,6 +15,10 @@
* [#7647](https://github.com/rubocop-hq/rubocop/issues/7647): Fix an `undefined method on_numblock` error when using Ruby 2.7's numbered parameters. ([@hanachin][])
* [#7675](https://github.com/rubocop-hq/rubocop/issues/7675): Fix a false negative for `Layout/SpaceBeforeFirstArg` when a vertical argument positions are aligned. ([@koic][])

### New features

* [#7659](https://github.com/rubocop-hq/rubocop/pull/7659): Layout/LineLength autocorrect now breaks up long lines with blocks. ([@maxh][])

### Changes

* [#7636](https://github.com/rubocop-hq/rubocop/issues/7636): Remove `console` from `Lint/Debugger` to prevent false positives. ([@gsamokovarov][])
Expand Down
31 changes: 30 additions & 1 deletion lib/rubocop/cop/layout/line_length.rb
Expand Up @@ -19,19 +19,25 @@ module Layout
#
# If autocorrection is enabled, the following Layout cops
# are recommended to further format the broken lines.
# (Many of these are enabled by default.)
#
# - ParameterAlignment
# - ArgumentAlignment
# - BlockAlignment
# - BlockDelimiters
# - BlockEndNewline
# - ClosingParenthesisIndentation
# - FirstArgumentIndentation
# - FirstArrayElementIndentation
# - FirstHashElementIndentation
# - FirstParameterIndentation
# - HashAlignment
# - IndentationWidth
# - MultilineArrayLineBreaks
# - MultilineBlockLayout
# - MultilineHashBraceLayout
# - MultilineHashKeyLineBreaks
# - MultilineMethodArgumentLineBreaks
# - ParameterAlignment
#
# Together, these cops will pretty print hashes, arrays,
# method calls, etc. For example, let's say the max columns
Expand Down Expand Up @@ -61,6 +67,10 @@ class LineLength < Cop

MSG = 'Line is too long. [%<length>d/%<max>d]'

def on_block(node)
check_for_breakable_block(node)
end

def on_potential_breakable_node(node)
check_for_breakable_node(node)
end
Expand Down Expand Up @@ -109,6 +119,25 @@ def check_for_breakable_semicolons(processed_source)
end
end

def check_for_breakable_block(block_node)
return unless block_node.single_line?

line_index = block_node.loc.line - 1
range = breakable_block_range(block_node)
pos = range.begin_pos + 1

breakable_range_by_line_index[line_index] =
range_between(pos, pos + 1)
end

def breakable_block_range(block_node)
if block_node.arguments?
block_node.arguments.loc.end
else
block_node.loc.begin
end
end

def breakable_range_after_semicolon(semicolon_token)
range = semicolon_token.pos
end_pos = range.end_pos
Expand Down
8 changes: 7 additions & 1 deletion manual/cops_layout.md
Expand Up @@ -2886,19 +2886,25 @@ method calls with argument lists.

If autocorrection is enabled, the following Layout cops
are recommended to further format the broken lines.
(Many of these are enabled by default.)

- ParameterAlignment
- ArgumentAlignment
- BlockAlignment
- BlockDelimiters
- BlockEndNewline
- ClosingParenthesisIndentation
- FirstArgumentIndentation
- FirstArrayElementIndentation
- FirstHashElementIndentation
- FirstParameterIndentation
- HashAlignment
- IndentationWidth
- MultilineArrayLineBreaks
- MultilineBlockLayout
- MultilineHashBraceLayout
- MultilineHashKeyLineBreaks
- MultilineMethodArgumentLineBreaks
- ParameterAlignment

Together, these cops will pretty print hashes, arrays,
method calls, etc. For example, let's say the max columns
Expand Down
58 changes: 58 additions & 0 deletions spec/rubocop/cop/layout/line_length_spec.rb
Expand Up @@ -735,6 +735,64 @@ def baz(bar)
end
end

context 'long blocks' do
context 'braces' do
it 'adds an offense and does correct it' do
expect_offense(<<~RUBY)
foo.select { |bar| 4444000039123123129993912312312999199291203123123 }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Line is too long. [70/40]
RUBY

expect_correction(<<~RUBY)
foo.select { |bar|
4444000039123123129993912312312999199291203123123 }
RUBY
end
end

context 'do/end' do
it 'adds an offense and does correct it' do
expect_offense(<<~RUBY)
foo.select do |bar| 4444000039123123129993912312312999199291203123 end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Line is too long. [70/40]
RUBY

expect_correction(<<~RUBY)
foo.select do |bar|
4444000039123123129993912312312999199291203123 end
RUBY
end
end

context 'let block' do
it 'adds an offense and does correct it' do
expect_offense(<<~RUBY)
let(:foobar) { BazBazBaz::BazBazBaz::BazBazBaz::BazBazBaz.baz(baz12) }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Line is too long. [70/40]
RUBY

expect_correction(<<~RUBY)
let(:foobar) {
BazBazBaz::BazBazBaz::BazBazBaz::BazBazBaz.baz(baz12) }
RUBY
end
end

context 'no spaces' do
it 'adds an offense and does correct it' do
expect_offense(<<~RUBY)
let(:foobar){BazBazBaz::BazBazBaz::BazBazBaz::BazBazBaz.baz(baz12345)}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Line is too long. [70/40]
RUBY

expect_correction(<<~RUBY)
let(:foobar){
BazBazBaz::BazBazBaz::BazBazBaz::BazBazBaz.baz(baz12345)}
RUBY
end
end
end

context 'semicolon' do
context 'when under limit' do
it 'does not add any offenses' do
Expand Down

0 comments on commit ac65140

Please sign in to comment.