From ac6514009940e7fd8cd72b7a5cf7e02b434eaa96 Mon Sep 17 00:00:00 2001 From: Buildkite Date: Sat, 18 Jan 2020 07:21:15 -0600 Subject: [PATCH] Add line length autocorrect for blocks --- CHANGELOG.md | 4 ++ lib/rubocop/cop/layout/line_length.rb | 31 ++++++++++- manual/cops_layout.md | 8 ++- spec/rubocop/cop/layout/line_length_spec.rb | 58 +++++++++++++++++++++ 4 files changed, 99 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dff3a0b2a94..5e0d10fc92b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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][]) diff --git a/lib/rubocop/cop/layout/line_length.rb b/lib/rubocop/cop/layout/line_length.rb index 085547a7c76..8f1b1e9e1b5 100644 --- a/lib/rubocop/cop/layout/line_length.rb +++ b/lib/rubocop/cop/layout/line_length.rb @@ -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 @@ -61,6 +67,10 @@ class LineLength < Cop MSG = 'Line is too long. [%d/%d]' + def on_block(node) + check_for_breakable_block(node) + end + def on_potential_breakable_node(node) check_for_breakable_node(node) end @@ -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 diff --git a/manual/cops_layout.md b/manual/cops_layout.md index 55964a332f9..1ae38bedc1f 100644 --- a/manual/cops_layout.md +++ b/manual/cops_layout.md @@ -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 diff --git a/spec/rubocop/cop/layout/line_length_spec.rb b/spec/rubocop/cop/layout/line_length_spec.rb index 2cb95ff1625..3f32300e4db 100644 --- a/spec/rubocop/cop/layout/line_length_spec.rb +++ b/spec/rubocop/cop/layout/line_length_spec.rb @@ -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