From 4207896010f17558b9e527b2d793a71c94f9d3c6 Mon Sep 17 00:00:00 2001 From: Draco Ater Date: Sat, 11 Apr 2020 12:15:16 +0300 Subject: [PATCH 1/6] Add support for tabs indentation. --- config/default.yml | 6 +- lib/rubocop/cop/layout/tab.rb | 52 +++- manual/cops_layout.md | 21 +- spec/rubocop/cli/cli_auto_gen_config_spec.rb | 12 +- spec/rubocop/cli/cli_options_spec.rb | 4 +- spec/rubocop/cop/layout/tab_spec.rb | 236 ++++++++++++++----- 6 files changed, 255 insertions(+), 76 deletions(-) diff --git a/config/default.yml b/config/default.yml index a4559adc8fb..90da8a29b5c 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1259,7 +1259,7 @@ Layout/SpaceInsideStringInterpolation: - no_space Layout/Tab: - Description: 'No hard tabs.' + Description: 'Consistent indentation either with tabs only or spaces only.' StyleGuide: '#spaces-indentation' Enabled: true VersionAdded: '0.49' @@ -1269,6 +1269,10 @@ Layout/Tab: # It is used during auto-correction to determine how many spaces should # replace each tab. IndentationWidth: ~ + EnforcedStyle: space + SupportedStyles: + - space + - tab Layout/TrailingEmptyLines: Description: 'Checks trailing blank lines and final newline.' diff --git a/lib/rubocop/cop/layout/tab.rb b/lib/rubocop/cop/layout/tab.rb index f9763602eff..5ccb5feae9a 100644 --- a/lib/rubocop/cop/layout/tab.rb +++ b/lib/rubocop/cop/layout/tab.rb @@ -5,9 +5,10 @@ module RuboCop module Cop module Layout - # This cop checks for tabs inside the source code. + # This cop checks that the indentation method is consistent. + # Either only tabs or only spaces are used for indentation. # - # @example + # @example EnforcedStyle: space (default) # # bad # # This example uses a tab to indent bar. # def foo @@ -20,17 +21,36 @@ module Layout # bar # end # + # @example EnforcedStyle: tab + # # bad + # # This example uses spaces to indent bar. + # def foo + # bar + # end + # + # # good + # # This example uses a tab to indent bar. + # def foo + # bar + # end class Tab < Cop include Alignment + include ConfigurableEnforcedStyle include RangeHelp - MSG = 'Tab detected.' + MSG_TAB = 'Tab detected.' + MSG_TAB_OUTSIDE_INDENTATION = 'Tab detected outside of indentation.' + MSG_SPACE_IN_INDENTATION = 'Space detected in indentation.' def investigate(processed_source) str_ranges = string_literal_ranges(processed_source.ast) processed_source.lines.each.with_index(1) do |line, lineno| - match = line.match(/\t+/) + match = if style == :space + line.match(/\t+/) + else + line.match(/\A\s* +/) or line.match(/\S\s*\t+/) + end next unless match range = source_range(processed_source.buffer, @@ -43,9 +63,17 @@ def investigate(processed_source) end def autocorrect(range) - lambda do |corrector| - spaces = ' ' * configured_indentation_width - corrector.replace(range, range.source.gsub(/\t/, spaces)) + if range.source.include?("\t") + lambda do |corrector| + spaces = ' ' * configured_indentation_width + corrector.replace(range, range.source.gsub(/\t/, spaces)) + end + else + lambda do |corrector| + corrector.replace(range, range.source.gsub(/\A\s+/) do |match| + "\t" * (match.size / configured_indentation_width) + end) + end end end @@ -69,6 +97,16 @@ def string_literal_ranges(ast) end end end + + def message(node) + if style == :space + MSG_TAB + elsif node.source.include?("\t") + MSG_TAB_OUTSIDE_INDENTATION + else + MSG_SPACE_IN_INDENTATION + end + end end end end diff --git a/manual/cops_layout.md b/manual/cops_layout.md index 2cccc572a34..19efd0b78da 100644 --- a/manual/cops_layout.md +++ b/manual/cops_layout.md @@ -4839,10 +4839,13 @@ Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChan --- | --- | --- | --- | --- Enabled | Yes | Yes | 0.49 | 0.51 -This cop checks for tabs inside the source code. +This cop checks that the indentation method is consistent. +Either only tabs or only spaces are used for indentation. ### Examples +#### EnforcedStyle: space (default) + ```ruby # bad # This example uses a tab to indent bar. @@ -4856,12 +4859,28 @@ def foo bar end ``` +#### EnforcedStyle: tab + +```ruby +# bad +# This example uses spaces to indent bar. +def foo + bar +end + +# good +# This example uses a tab to indent bar. +def foo + bar +end +``` ### Configurable attributes Name | Default value | Configurable values --- | --- | --- IndentationWidth | `` | Integer +EnforcedStyle | `space` | `space`, `tab` ### References diff --git a/spec/rubocop/cli/cli_auto_gen_config_spec.rb b/spec/rubocop/cli/cli_auto_gen_config_spec.rb index 95a4aa82bb9..a4651803ea8 100644 --- a/spec/rubocop/cli/cli_auto_gen_config_spec.rb +++ b/spec/rubocop/cli/cli_auto_gen_config_spec.rb @@ -606,7 +606,8 @@ def a; end '', '# Offense count: 1', '# Cop supports --auto-correct.', - '# Configuration parameters: IndentationWidth.', + '# Configuration parameters: IndentationWidth, EnforcedStyle.', + '# SupportedStyles: space, tab', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", @@ -705,7 +706,8 @@ def a; end '', '# Offense count: 1', '# Cop supports --auto-correct.', - '# Configuration parameters: IndentationWidth.', + '# Configuration parameters: IndentationWidth, EnforcedStyle.', + '# SupportedStyles: space, tab', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", @@ -788,7 +790,8 @@ def a; end '', '# Offense count: 1', '# Cop supports --auto-correct.', - '# Configuration parameters: IndentationWidth.', + '# Configuration parameters: IndentationWidth, EnforcedStyle.', + '# SupportedStyles: space, tab', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'"] @@ -909,7 +912,8 @@ def a; end " - 'example1.rb'", '', '# Cop supports --auto-correct.', - '# Configuration parameters: IndentationWidth.', + '# Configuration parameters: IndentationWidth, EnforcedStyle.', + '# SupportedStyles: space, tab', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", diff --git a/spec/rubocop/cli/cli_options_spec.rb b/spec/rubocop/cli/cli_options_spec.rb index ce4a895bb7c..fb70199922e 100644 --- a/spec/rubocop/cli/cli_options_spec.rb +++ b/spec/rubocop/cli/cli_options_spec.rb @@ -920,7 +920,7 @@ def full_description_of_cop(cop) expect(stdout).to match( ['# Supports --auto-correct', 'Layout/Tab:', - ' Description: No hard tabs.', + ' Description: Consistent indentation either with tabs only or spaces only.', /^ StyleGuide: ('|")#spaces-indentation('|")$/, ' Enabled: true', /^ VersionAdded: '[0-9\.]+'$/, @@ -945,7 +945,7 @@ def full_description_of_cop(cop) expect(stdout).to match( ['# Supports --auto-correct', 'Layout/Tab:', - ' Description: No hard tabs.', + ' Description: Consistent indentation either with tabs only or spaces only.', /^ StyleGuide: ('|")#spaces-indentation('|")$/, ' Enabled: true'].join("\n") ) diff --git a/spec/rubocop/cop/layout/tab_spec.rb b/spec/rubocop/cop/layout/tab_spec.rb index 194f6f07f8c..7f9983cc0b5 100644 --- a/spec/rubocop/cop/layout/tab_spec.rb +++ b/spec/rubocop/cop/layout/tab_spec.rb @@ -4,101 +4,215 @@ subject(:cop) { described_class.new(config) } let(:config) do - RuboCop::Config.new('Layout/IndentationWidth' => { 'Width' => 2 }) + supported_styles = { + 'SupportedStyles' => %w[space tab] + } + RuboCop::Config.new( + 'Layout/IndentationWidth' => { 'Width' => 2 }, + 'Layout/Tab' => cop_config.merge(supported_styles) + ) end - it 'registers an offense for a line indented with tab' do - expect_offense(<<~RUBY) + context 'when EnforcedStyle is space' do + let(:cop_config) { { 'EnforcedStyle' => 'space' } } + + it 'registers an offense for a line indented with tab' do + expect_offense(<<~RUBY) x = 0 ^ Tab detected. - RUBY - end + RUBY + end - it 'registers an offense for a line indented with multiple tabs' do - expect_offense(<<~RUBY) + it 'registers an offense for a line indented with multiple tabs' do + expect_offense(<<~RUBY) x = 0 ^^^ Tab detected. - RUBY - end + RUBY + end - it 'registers an offense for a line indented with mixed whitespace' do - expect_offense(<<-'RUBY') + it 'registers an offense for a line indented with mixed whitespace' do + expect_offense(<<-'RUBY') x = 0 ^ Tab detected. - RUBY - end + RUBY + end - it 'registers offenses before __END__ but not after' do - expect_offense(<<~RUBY) + it 'registers offenses before __END__ but not after' do + expect_offense(<<~RUBY) \tx = 0 ^ Tab detected. __END__ \tx = 0 - RUBY - end + RUBY + end - it 'registers an offense for a tab other than indentation' do - expect_offense(<<~RUBY) + it 'registers an offense for a tab other than indentation' do + expect_offense(<<~RUBY) foo \t bar ^ Tab detected. - RUBY - end + RUBY + end - it 'registers an offense for tabs between string literals' do - expect_offense(<<~RUBY) + it 'registers an offense for tabs between string literals' do + expect_offense(<<~RUBY) 'foo'\t'bar' ^ Tab detected. - RUBY - end + RUBY + end - it 'accepts a line with tab in a string' do - expect_no_offenses("(x = \"\t\")") - end + it 'accepts a line with tab in a string' do + expect_no_offenses("(x = \"\t\")") + end - it 'accepts a line which begins with tab in a string' do - expect_no_offenses("x = '\n\thello'") - end + it 'accepts a line which begins with tab in a string' do + expect_no_offenses("x = '\n\thello'") + end - it 'accepts a line which begins with tab in a heredoc' do - expect_no_offenses("x = < 3, 'EnforcedStyle' => 'space' } } + + it 'uses the configured number of spaces to replace a tab' do + new_source = autocorrect_source("\tx = 0") + + expect(new_source).to eq(' x = 0') + end + end end - context 'custom indentation width' do - let(:config) do - RuboCop::Config.new('Layout/Tab' => { - 'IndentationWidth' => 3 - }, - 'Layout/IndentationWidth' => { 'Width' => 2 }) + context 'when EnforcedStyle is tab' do + let(:cop_config) { { 'EnforcedStyle' => 'tab' } } + + it 'registers an offense for a line indented with space' do + expect_offense(<<~RUBY) + x = 0 + ^^ Space detected in indentation. + RUBY end - it 'uses the configured number of spaces to replace a tab' do - new_source = autocorrect_source("\tx = 0") + it 'registers an offense for a line indented with multiple spaces' do + expect_offense(<<~RUBY) + x = 0 + ^^^^^^ Space detected in indentation. + RUBY + end - expect(new_source).to eq(' x = 0') + it 'registers an offense for a line indented with mixed whitespace' do + expect_offense(<<~'RUBY') + x = 0 + ^ Space detected in indentation. + RUBY + end + + it 'registers offenses before __END__ but not after' do + expect_offense(<<~RUBY) + x = 0 + ^^ Space detected in indentation. + __END__ + x = 0 + RUBY + end + + it 'registers an offense for a tab other than indentation' do + expect_offense(<<~RUBY) + \tfoo \t bar + ^^^ Tab detected outside of indentation. + RUBY + end + + it 'registers an offense for tabs between string literals' do + expect_offense(<<~RUBY) + 'foo'\t'bar' + ^^ Tab detected outside of indentation. + RUBY + end + + it 'accepts a line with tab in a string' do + expect_no_offenses("(x = \"\t\")") + end + + it 'accepts a line which begins with tab in a string' do + expect_no_offenses("x = '\n\thello'") + end + + it 'accepts a line which begins with tab in a heredoc' do + expect_no_offenses("x = < 3, 'EnforcedStyle' => 'tab' } } + + it 'uses the configured number of spaces to replace with a tab' do + new_source = autocorrect_source(" x = 0") + + expect(new_source).to eq("\t\tx = 0") + end end end end From f2e7a1b4d31440159987fc529fe8ca6d8b653ae6 Mon Sep 17 00:00:00 2001 From: Draco Ater Date: Sat, 11 Apr 2020 15:55:17 +0300 Subject: [PATCH 2/6] Change SupportedStyles for Layout/Tab to [spaces, tabs]. Fix linting issues. --- config/default.yml | 6 +- lib/rubocop/cop/layout/tab.rb | 46 +++++++----- manual/cops_layout.md | 6 +- spec/rubocop/cli/cli_auto_gen_config_spec.rb | 8 +-- spec/rubocop/cli/cli_options_spec.rb | 4 +- spec/rubocop/cop/layout/tab_spec.rb | 75 +++++++++++--------- 6 files changed, 81 insertions(+), 64 deletions(-) diff --git a/config/default.yml b/config/default.yml index 90da8a29b5c..04a5996781c 100644 --- a/config/default.yml +++ b/config/default.yml @@ -1269,10 +1269,10 @@ Layout/Tab: # It is used during auto-correction to determine how many spaces should # replace each tab. IndentationWidth: ~ - EnforcedStyle: space + EnforcedStyle: spaces SupportedStyles: - - space - - tab + - spaces + - tabs Layout/TrailingEmptyLines: Description: 'Checks trailing blank lines and final newline.' diff --git a/lib/rubocop/cop/layout/tab.rb b/lib/rubocop/cop/layout/tab.rb index 5ccb5feae9a..3417ec209d7 100644 --- a/lib/rubocop/cop/layout/tab.rb +++ b/lib/rubocop/cop/layout/tab.rb @@ -8,7 +8,7 @@ module Layout # This cop checks that the indentation method is consistent. # Either only tabs or only spaces are used for indentation. # - # @example EnforcedStyle: space (default) + # @example EnforcedStyle: spaces (default) # # bad # # This example uses a tab to indent bar. # def foo @@ -21,7 +21,7 @@ module Layout # bar # end # - # @example EnforcedStyle: tab + # @example EnforcedStyle: tabs # # bad # # This example uses spaces to indent bar. # def foo @@ -46,11 +46,7 @@ def investigate(processed_source) str_ranges = string_literal_ranges(processed_source.ast) processed_source.lines.each.with_index(1) do |line, lineno| - match = if style == :space - line.match(/\t+/) - else - line.match(/\A\s* +/) or line.match(/\S\s*\t+/) - end + match = find_offence(line) next unless match range = source_range(processed_source.buffer, @@ -64,21 +60,37 @@ def investigate(processed_source) def autocorrect(range) if range.source.include?("\t") - lambda do |corrector| - spaces = ' ' * configured_indentation_width - corrector.replace(range, range.source.gsub(/\t/, spaces)) - end + autocorrect_lambda_for_tabs(range) else - lambda do |corrector| - corrector.replace(range, range.source.gsub(/\A\s+/) do |match| - "\t" * (match.size / configured_indentation_width) - end) - end + autocorrect_lambda_for_spaces(range) end end private + def find_offence(line) + if style == :spaces + line.match(/\t+/) + else + line.match(/\A\s* +/) || line.match(/\S\s*\t+/) + end + end + + def autocorrect_lambda_for_tabs(range) + lambda do |corrector| + spaces = ' ' * configured_indentation_width + corrector.replace(range, range.source.gsub(/\t/, spaces)) + end + end + + def autocorrect_lambda_for_spaces(range) + lambda do |corrector| + corrector.replace(range, range.source.gsub(/\A\s+/) do |match| + "\t" * (match.size / configured_indentation_width) + end) + end + end + def in_string_literal?(ranges, tabs_range) ranges.any? { |range| range.contains?(tabs_range) } end @@ -99,7 +111,7 @@ def string_literal_ranges(ast) end def message(node) - if style == :space + if style == :spaces MSG_TAB elsif node.source.include?("\t") MSG_TAB_OUTSIDE_INDENTATION diff --git a/manual/cops_layout.md b/manual/cops_layout.md index 19efd0b78da..3d0accdf952 100644 --- a/manual/cops_layout.md +++ b/manual/cops_layout.md @@ -4844,7 +4844,7 @@ Either only tabs or only spaces are used for indentation. ### Examples -#### EnforcedStyle: space (default) +#### EnforcedStyle: spaces (default) ```ruby # bad @@ -4859,7 +4859,7 @@ def foo bar end ``` -#### EnforcedStyle: tab +#### EnforcedStyle: tabs ```ruby # bad @@ -4880,7 +4880,7 @@ end Name | Default value | Configurable values --- | --- | --- IndentationWidth | `` | Integer -EnforcedStyle | `space` | `space`, `tab` +EnforcedStyle | `spaces` | `spaces`, `tabs` ### References diff --git a/spec/rubocop/cli/cli_auto_gen_config_spec.rb b/spec/rubocop/cli/cli_auto_gen_config_spec.rb index a4651803ea8..e9d5baf0be4 100644 --- a/spec/rubocop/cli/cli_auto_gen_config_spec.rb +++ b/spec/rubocop/cli/cli_auto_gen_config_spec.rb @@ -607,7 +607,7 @@ def a; end '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: IndentationWidth, EnforcedStyle.', - '# SupportedStyles: space, tab', + '# SupportedStyles: spaces, tabs', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", @@ -707,7 +707,7 @@ def a; end '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: IndentationWidth, EnforcedStyle.', - '# SupportedStyles: space, tab', + '# SupportedStyles: spaces, tabs', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", @@ -791,7 +791,7 @@ def a; end '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: IndentationWidth, EnforcedStyle.', - '# SupportedStyles: space, tab', + '# SupportedStyles: spaces, tabs', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'"] @@ -913,7 +913,7 @@ def a; end '', '# Cop supports --auto-correct.', '# Configuration parameters: IndentationWidth, EnforcedStyle.', - '# SupportedStyles: space, tab', + '# SupportedStyles: spaces, tabs', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", diff --git a/spec/rubocop/cli/cli_options_spec.rb b/spec/rubocop/cli/cli_options_spec.rb index fb70199922e..92661f8e115 100644 --- a/spec/rubocop/cli/cli_options_spec.rb +++ b/spec/rubocop/cli/cli_options_spec.rb @@ -920,7 +920,7 @@ def full_description_of_cop(cop) expect(stdout).to match( ['# Supports --auto-correct', 'Layout/Tab:', - ' Description: Consistent indentation either with tabs only or spaces only.', + ' Description: Consistent indentation either with tabs only or spaces only.', # rubocop:disable Layout/LineLength /^ StyleGuide: ('|")#spaces-indentation('|")$/, ' Enabled: true', /^ VersionAdded: '[0-9\.]+'$/, @@ -945,7 +945,7 @@ def full_description_of_cop(cop) expect(stdout).to match( ['# Supports --auto-correct', 'Layout/Tab:', - ' Description: Consistent indentation either with tabs only or spaces only.', + ' Description: Consistent indentation either with tabs only or spaces only.', # rubocop:disable Layout/LineLength /^ StyleGuide: ('|")#spaces-indentation('|")$/, ' Enabled: true'].join("\n") ) diff --git a/spec/rubocop/cop/layout/tab_spec.rb b/spec/rubocop/cop/layout/tab_spec.rb index 7f9983cc0b5..ee654ca7a1a 100644 --- a/spec/rubocop/cop/layout/tab_spec.rb +++ b/spec/rubocop/cop/layout/tab_spec.rb @@ -5,7 +5,7 @@ let(:config) do supported_styles = { - 'SupportedStyles' => %w[space tab] + 'SupportedStyles' => %w[spaces tabs] } RuboCop::Config.new( 'Layout/IndentationWidth' => { 'Width' => 2 }, @@ -14,49 +14,49 @@ end context 'when EnforcedStyle is space' do - let(:cop_config) { { 'EnforcedStyle' => 'space' } } + let(:cop_config) { { 'EnforcedStyle' => 'spaces' } } it 'registers an offense for a line indented with tab' do expect_offense(<<~RUBY) - x = 0 - ^ Tab detected. + x = 0 + ^ Tab detected. RUBY end it 'registers an offense for a line indented with multiple tabs' do expect_offense(<<~RUBY) - x = 0 - ^^^ Tab detected. + x = 0 + ^^^ Tab detected. RUBY end it 'registers an offense for a line indented with mixed whitespace' do expect_offense(<<-'RUBY') - x = 0 - ^ Tab detected. + x = 0 + ^ Tab detected. RUBY end it 'registers offenses before __END__ but not after' do expect_offense(<<~RUBY) - \tx = 0 - ^ Tab detected. - __END__ - \tx = 0 + \tx = 0 + ^ Tab detected. + __END__ + \tx = 0 RUBY end it 'registers an offense for a tab other than indentation' do expect_offense(<<~RUBY) - foo \t bar - ^ Tab detected. + foo \t bar + ^ Tab detected. RUBY end it 'registers an offense for tabs between string literals' do expect_offense(<<~RUBY) - 'foo'\t'bar' - ^ Tab detected. + 'foo'\t'bar' + ^ Tab detected. RUBY end @@ -98,11 +98,13 @@ it 'auto-corrects a line with tab other than indentation' do new_source = autocorrect_source("foo \t bar") - expect(new_source).to eq("foo bar") + expect(new_source).to eq('foo bar') end context 'custom indentation width' do - let(:cop_config) { { 'IndentationWidth' => 3, 'EnforcedStyle' => 'space' } } + let(:cop_config) do + { 'IndentationWidth' => 3, 'EnforcedStyle' => 'spaces' } + end it 'uses the configured number of spaces to replace a tab' do new_source = autocorrect_source("\tx = 0") @@ -113,35 +115,35 @@ end context 'when EnforcedStyle is tab' do - let(:cop_config) { { 'EnforcedStyle' => 'tab' } } + let(:cop_config) { { 'EnforcedStyle' => 'tabs' } } it 'registers an offense for a line indented with space' do expect_offense(<<~RUBY) - x = 0 - ^^ Space detected in indentation. + x = 0 + ^^ Space detected in indentation. RUBY end it 'registers an offense for a line indented with multiple spaces' do expect_offense(<<~RUBY) - x = 0 - ^^^^^^ Space detected in indentation. + x = 0 + ^^^^^^ Space detected in indentation. RUBY end it 'registers an offense for a line indented with mixed whitespace' do expect_offense(<<~'RUBY') - x = 0 - ^ Space detected in indentation. + x = 0 + ^ Space detected in indentation. RUBY end it 'registers offenses before __END__ but not after' do expect_offense(<<~RUBY) - x = 0 - ^^ Space detected in indentation. - __END__ - x = 0 + x = 0 + ^^ Space detected in indentation. + __END__ + x = 0 RUBY end @@ -154,8 +156,8 @@ it 'registers an offense for tabs between string literals' do expect_offense(<<~RUBY) - 'foo'\t'bar' - ^^ Tab detected outside of indentation. + 'foo'\t'bar' + ^^ Tab detected outside of indentation. RUBY end @@ -176,7 +178,7 @@ end it 'auto-corrects a line indented with space' do - new_source = autocorrect_source(" x = 0") + new_source = autocorrect_source(' x = 0') expect(new_source).to eq("\tx = 0") end @@ -185,7 +187,8 @@ expect(new_source).to eq("\t\t\tx = 0") end - it 'auto-corrects a line indented with fractional number of indentation groups by ' do + it 'auto-corrects a line indented with fractional number of'\ + 'indentation groups by rounding down' do new_source = autocorrect_source(' x = 0') expect(new_source).to eq("\tx = 0") end @@ -206,10 +209,12 @@ end context 'custom indentation width' do - let(:cop_config) { { 'IndentationWidth' => 3, 'EnforcedStyle' => 'tab' } } + let(:cop_config) do + { 'IndentationWidth' => 3, 'EnforcedStyle' => 'tabs' } + end it 'uses the configured number of spaces to replace with a tab' do - new_source = autocorrect_source(" x = 0") + new_source = autocorrect_source(' x = 0') expect(new_source).to eq("\t\tx = 0") end From a15f80d592235d80961e203354f7a6bc8a9c6357 Mon Sep 17 00:00:00 2001 From: Draco Ater Date: Mon, 13 Apr 2020 23:28:47 +0300 Subject: [PATCH 3/6] Rename Layout/Tab cop into Layout/IndentationStyle. --- config/default.yml | 32 +++--- lib/rubocop.rb | 2 +- lib/rubocop/cop/badge.rb | 10 +- .../layout/{tab.rb => indentation_style.rb} | 22 ++-- lib/rubocop/cop/layout/line_length.rb | 2 +- lib/rubocop/cop/mixin/line_length_help.rb | 2 +- lib/rubocop/cop/mixin/statement_modifier.rb | 7 +- lib/rubocop/cop/style/if_unless_modifier.rb | 2 +- manual/cops.md | 2 +- manual/cops_layout.md | 108 +++++++++--------- manual/cops_style.md | 2 +- spec/rubocop/cli/cli_auto_gen_config_spec.rb | 54 ++++----- spec/rubocop/cli/cli_options_spec.rb | 45 ++++---- spec/rubocop/comment_config_spec.rb | 6 +- spec/rubocop/cop/generator_spec.rb | 10 +- ...{tab_spec.rb => indentation_style_spec.rb} | 54 ++++----- spec/rubocop/cop/layout/line_length_spec.rb | 4 +- .../redundant_cop_disable_directive_spec.rb | 22 ++-- .../cop/style/if_unless_modifier_spec.rb | 10 +- spec/rubocop/cop/team_spec.rb | 4 +- spec/rubocop/yaml_duplication_checker_spec.rb | 14 +-- 21 files changed, 203 insertions(+), 211 deletions(-) rename lib/rubocop/cop/layout/{tab.rb => indentation_style.rb} (82%) rename spec/rubocop/cop/layout/{tab_spec.rb => indentation_style_spec.rb} (80%) diff --git a/config/default.yml b/config/default.yml index 04a5996781c..66f9a52af5a 100644 --- a/config/default.yml +++ b/config/default.yml @@ -801,6 +801,22 @@ Layout/IndentationConsistency: # A reference to `EnforcedStyle: indented_internal_methods`. - https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#follow-the-coding-conventions +Layout/IndentationStyle: + Description: 'Consistent indentation either with tabs only or spaces only.' + StyleGuide: '#spaces-indentation' + Enabled: true + VersionAdded: '0.49' + VersionChanged: '0.51' + # By default, the indentation width from Layout/IndentationWidth is used + # But it can be overridden by setting this parameter + # It is used during auto-correction to determine how many spaces should + # replace each tab. + IndentationWidth: ~ + EnforcedStyle: spaces + SupportedStyles: + - spaces + - tabs + Layout/IndentationWidth: Description: 'Use 2 spaces for indentation.' StyleGuide: '#spaces-indentation' @@ -1258,22 +1274,6 @@ Layout/SpaceInsideStringInterpolation: - space - no_space -Layout/Tab: - Description: 'Consistent indentation either with tabs only or spaces only.' - StyleGuide: '#spaces-indentation' - Enabled: true - VersionAdded: '0.49' - VersionChanged: '0.51' - # By default, the indentation width from Layout/IndentationWidth is used - # But it can be overridden by setting this parameter - # It is used during auto-correction to determine how many spaces should - # replace each tab. - IndentationWidth: ~ - EnforcedStyle: spaces - SupportedStyles: - - spaces - - tabs - Layout/TrailingEmptyLines: Description: 'Checks trailing blank lines and final newline.' StyleGuide: '#newline-eof' diff --git a/lib/rubocop.rb b/lib/rubocop.rb index 60717410ba9..bc0f8c1a75c 100644 --- a/lib/rubocop.rb +++ b/lib/rubocop.rb @@ -235,6 +235,7 @@ require_relative 'rubocop/cop/layout/heredoc_argument_closing_parenthesis' require_relative 'rubocop/cop/layout/heredoc_indentation' require_relative 'rubocop/cop/layout/indentation_consistency' +require_relative 'rubocop/cop/layout/indentation_style' require_relative 'rubocop/cop/layout/indentation_width' require_relative 'rubocop/cop/layout/initial_indentation' require_relative 'rubocop/cop/layout/leading_comment_space' @@ -277,7 +278,6 @@ require_relative 'rubocop/cop/layout/space_inside_range_literal' require_relative 'rubocop/cop/layout/space_inside_reference_brackets' require_relative 'rubocop/cop/layout/space_inside_string_interpolation' -require_relative 'rubocop/cop/layout/tab' require_relative 'rubocop/cop/layout/trailing_empty_lines' require_relative 'rubocop/cop/layout/trailing_whitespace' diff --git a/lib/rubocop/cop/badge.rb b/lib/rubocop/cop/badge.rb index 7f4260dd103..6ad6fc89ff9 100644 --- a/lib/rubocop/cop/badge.rb +++ b/lib/rubocop/cop/badge.rb @@ -4,11 +4,11 @@ module RuboCop module Cop # Identifier of all cops containing a department and cop name. # - # All cops are identified by their badge. For example, the badge - # for `RuboCop::Cop::Layout::Tab` is `Layout/Tab`. Badges can be - # parsed as either `Department/CopName` or just `CopName` to allow - # for badge references in source files that omit the department - # for RuboCop to infer. + # All cops are identified by their badge. For example, the badge for + # `RuboCop::Cop::Layout::IndentationStyle` is `Layout/IndentationStyle`. + # Badges can be parsed as either `Department/CopName` or just `CopName` to + # allow for badge references in source files that omit the department for + # RuboCop to infer. class Badge # Error raised when a badge parse fails. class InvalidBadge < Error diff --git a/lib/rubocop/cop/layout/tab.rb b/lib/rubocop/cop/layout/indentation_style.rb similarity index 82% rename from lib/rubocop/cop/layout/tab.rb rename to lib/rubocop/cop/layout/indentation_style.rb index 3417ec209d7..d86c50b9e64 100644 --- a/lib/rubocop/cop/layout/tab.rb +++ b/lib/rubocop/cop/layout/indentation_style.rb @@ -6,7 +6,7 @@ module RuboCop module Cop module Layout # This cop checks that the indentation method is consistent. - # Either only tabs or only spaces are used for indentation. + # Either tabs only or spaces only are used for indentation. # # @example EnforcedStyle: spaces (default) # # bad @@ -33,14 +33,12 @@ module Layout # def foo # bar # end - class Tab < Cop + class IndentationStyle < Cop include Alignment include ConfigurableEnforcedStyle include RangeHelp - MSG_TAB = 'Tab detected.' - MSG_TAB_OUTSIDE_INDENTATION = 'Tab detected outside of indentation.' - MSG_SPACE_IN_INDENTATION = 'Space detected in indentation.' + MSG = '%s detected in indentation.' def investigate(processed_source) str_ranges = string_literal_ranges(processed_source.ast) @@ -70,9 +68,9 @@ def autocorrect(range) def find_offence(line) if style == :spaces - line.match(/\t+/) + line.match(/\A\s*\t+/) else - line.match(/\A\s* +/) || line.match(/\S\s*\t+/) + line.match(/\A\s* +/) end end @@ -110,14 +108,8 @@ def string_literal_ranges(ast) end end - def message(node) - if style == :spaces - MSG_TAB - elsif node.source.include?("\t") - MSG_TAB_OUTSIDE_INDENTATION - else - MSG_SPACE_IN_INDENTATION - end + def message(_node) + format(MSG, type: style == :spaces ? 'Tab' : 'Space') end end end diff --git a/lib/rubocop/cop/layout/line_length.rb b/lib/rubocop/cop/layout/line_length.rb index 503ca44255b..ceb25b1629d 100644 --- a/lib/rubocop/cop/layout/line_length.rb +++ b/lib/rubocop/cop/layout/line_length.rb @@ -8,7 +8,7 @@ module Layout # This cop checks the length of lines in the source code. # The maximum length is configurable. # The tab size is configured in the `IndentationWidth` - # of the `Layout/Tab` cop. + # of the `Layout/IndentationStyle` cop. # It also ignores a shebang line by default. # # This cop has some autocorrection capabilities. diff --git a/lib/rubocop/cop/mixin/line_length_help.rb b/lib/rubocop/cop/mixin/line_length_help.rb index 77e07067248..293ef38c27d 100644 --- a/lib/rubocop/cop/mixin/line_length_help.rb +++ b/lib/rubocop/cop/mixin/line_length_help.rb @@ -63,7 +63,7 @@ def indentation_difference(line) end def tab_indentation_width - config.for_cop('Layout/Tab')['IndentationWidth'] + config.for_cop('Layout/IndentationStyle')['IndentationWidth'] end def uri_regexp diff --git a/lib/rubocop/cop/mixin/statement_modifier.rb b/lib/rubocop/cop/mixin/statement_modifier.rb index f4816949d2b..dff5564c312 100644 --- a/lib/rubocop/cop/mixin/statement_modifier.rb +++ b/lib/rubocop/cop/mixin/statement_modifier.rb @@ -58,12 +58,13 @@ def max_line_length end def indentation_multiplier - return 1 if config.for_cop('Layout/Tab')['Enabled'] + return 1 if config.for_cop('Layout/IndentationStyle')['Enabled'] default_configuration = RuboCop::ConfigLoader.default_configuration - config.for_cop('Layout/Tab')['IndentationWidth'] || + config.for_cop('Layout/IndentationStyle')['IndentationWidth'] || config.for_cop('Layout/IndentationWidth')['Width'] || - default_configuration.for_cop('Layout/Tab')['IndentationWidth'] || + default_configuration + .for_cop('Layout/IndentationStyle')['IndentationWidth'] || default_configuration.for_cop('Layout/IndentationWidth')['Width'] end end diff --git a/lib/rubocop/cop/style/if_unless_modifier.rb b/lib/rubocop/cop/style/if_unless_modifier.rb index 23825b58937..a7c81ff622c 100644 --- a/lib/rubocop/cop/style/if_unless_modifier.rb +++ b/lib/rubocop/cop/style/if_unless_modifier.rb @@ -9,7 +9,7 @@ module Style # # The maximum line length is configured in the `Layout/LineLength` # cop. The tab size is configured in the `IndentationWidth` of the - # `Layout/Tab` cop. + # `Layout/IndentationStyle` cop. # # @example # # bad diff --git a/manual/cops.md b/manual/cops.md index aafcfc2968e..9d053f5a31c 100644 --- a/manual/cops.md +++ b/manual/cops.md @@ -128,6 +128,7 @@ In the following section you find all available cops: * [Layout/HeredocArgumentClosingParenthesis](cops_layout.md#layoutheredocargumentclosingparenthesis) * [Layout/HeredocIndentation](cops_layout.md#layoutheredocindentation) * [Layout/IndentationConsistency](cops_layout.md#layoutindentationconsistency) +* [Layout/IndentationStyle](cops_layout.md#layoutindentationstyle) * [Layout/IndentationWidth](cops_layout.md#layoutindentationwidth) * [Layout/InitialIndentation](cops_layout.md#layoutinitialindentation) * [Layout/LeadingCommentSpace](cops_layout.md#layoutleadingcommentspace) @@ -170,7 +171,6 @@ In the following section you find all available cops: * [Layout/SpaceInsideRangeLiteral](cops_layout.md#layoutspaceinsiderangeliteral) * [Layout/SpaceInsideReferenceBrackets](cops_layout.md#layoutspaceinsidereferencebrackets) * [Layout/SpaceInsideStringInterpolation](cops_layout.md#layoutspaceinsidestringinterpolation) -* [Layout/Tab](cops_layout.md#layouttab) * [Layout/TrailingEmptyLines](cops_layout.md#layouttrailingemptylines) * [Layout/TrailingWhitespace](cops_layout.md#layouttrailingwhitespace) diff --git a/manual/cops_layout.md b/manual/cops_layout.md index 3d0accdf952..7894edb5b3b 100644 --- a/manual/cops_layout.md +++ b/manual/cops_layout.md @@ -2720,6 +2720,59 @@ EnforcedStyle | `normal` | `normal`, `indented_internal_methods` * [https://rubystyle.guide#spaces-indentation](https://rubystyle.guide#spaces-indentation) * [https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#follow-the-coding-conventions](https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#follow-the-coding-conventions) +## Layout/IndentationStyle + +Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged +--- | --- | --- | --- | --- +Enabled | Yes | Yes | 0.49 | 0.51 + +This cop checks that the indentation method is consistent. +Either tabs only or spaces only are used for indentation. + +### Examples + +#### EnforcedStyle: spaces (default) + +```ruby +# bad +# This example uses a tab to indent bar. +def foo + bar +end + +# good +# This example uses spaces to indent bar. +def foo + bar +end +``` +#### EnforcedStyle: tabs + +```ruby +# bad +# This example uses spaces to indent bar. +def foo + bar +end + +# good +# This example uses a tab to indent bar. +def foo + bar +end +``` + +### Configurable attributes + +Name | Default value | Configurable values +--- | --- | --- +IndentationWidth | `` | Integer +EnforcedStyle | `spaces` | `spaces`, `tabs` + +### References + +* [https://rubystyle.guide#spaces-indentation](https://rubystyle.guide#spaces-indentation) + ## Layout/IndentationWidth Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged @@ -2916,7 +2969,7 @@ Enabled | Yes | Yes | 0.25 | 0.78 This cop checks the length of lines in the source code. The maximum length is configurable. The tab size is configured in the `IndentationWidth` -of the `Layout/Tab` cop. +of the `Layout/IndentationStyle` cop. It also ignores a shebang line by default. This cop has some autocorrection capabilities. @@ -4833,59 +4886,6 @@ EnforcedStyle | `no_space` | `space`, `no_space` * [https://rubystyle.guide#string-interpolation](https://rubystyle.guide#string-interpolation) -## Layout/Tab - -Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged ---- | --- | --- | --- | --- -Enabled | Yes | Yes | 0.49 | 0.51 - -This cop checks that the indentation method is consistent. -Either only tabs or only spaces are used for indentation. - -### Examples - -#### EnforcedStyle: spaces (default) - -```ruby -# bad -# This example uses a tab to indent bar. -def foo - bar -end - -# good -# This example uses spaces to indent bar. -def foo - bar -end -``` -#### EnforcedStyle: tabs - -```ruby -# bad -# This example uses spaces to indent bar. -def foo - bar -end - -# good -# This example uses a tab to indent bar. -def foo - bar -end -``` - -### Configurable attributes - -Name | Default value | Configurable values ---- | --- | --- -IndentationWidth | `` | Integer -EnforcedStyle | `spaces` | `spaces`, `tabs` - -### References - -* [https://rubystyle.guide#spaces-indentation](https://rubystyle.guide#spaces-indentation) - ## Layout/TrailingEmptyLines Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged diff --git a/manual/cops_style.md b/manual/cops_style.md index 856d78d29c8..54615cef270 100644 --- a/manual/cops_style.md +++ b/manual/cops_style.md @@ -2820,7 +2820,7 @@ written as modifier `if`/`unless`. The cop also checks for modifier The maximum line length is configured in the `Layout/LineLength` cop. The tab size is configured in the `IndentationWidth` of the -`Layout/Tab` cop. +`Layout/IndentationStyle` cop. ### Examples diff --git a/spec/rubocop/cli/cli_auto_gen_config_spec.rb b/spec/rubocop/cli/cli_auto_gen_config_spec.rb index e9d5baf0be4..51063e1d53d 100644 --- a/spec/rubocop/cli/cli_auto_gen_config_spec.rb +++ b/spec/rubocop/cli/cli_auto_gen_config_spec.rb @@ -591,6 +591,14 @@ def a; end '', '# Offense count: 1', '# Cop supports --auto-correct.', + '# Configuration parameters: IndentationWidth, EnforcedStyle.', + '# SupportedStyles: spaces, tabs', + 'Layout/IndentationStyle:', + ' Exclude:', + " - 'example2.rb'", + '', + '# Offense count: 1', + '# Cop supports --auto-correct.', 'Layout/InitialIndentation:', ' Exclude:', " - 'example2.rb'", @@ -604,14 +612,6 @@ def a; end ' Exclude:', " - 'example1.rb'", '', - '# Offense count: 1', - '# Cop supports --auto-correct.', - '# Configuration parameters: IndentationWidth, EnforcedStyle.', - '# SupportedStyles: spaces, tabs', - 'Layout/Tab:', - ' Exclude:', - " - 'example2.rb'", - '', '# Offense count: 2', '# Cop supports --auto-correct.', '# Configuration parameters: AllowInHeredoc.', @@ -691,6 +691,14 @@ def a; end '', '# Offense count: 1', '# Cop supports --auto-correct.', + '# Configuration parameters: IndentationWidth, EnforcedStyle.', + '# SupportedStyles: spaces, tabs', + 'Layout/IndentationStyle:', + ' Exclude:', + " - 'example2.rb'", + '', + '# Offense count: 1', + '# Cop supports --auto-correct.', 'Layout/InitialIndentation:', ' Exclude:', " - 'example2.rb'", @@ -704,14 +712,6 @@ def a; end ' Exclude:', " - 'example1.rb'", '', - '# Offense count: 1', - '# Cop supports --auto-correct.', - '# Configuration parameters: IndentationWidth, EnforcedStyle.', - '# SupportedStyles: spaces, tabs', - 'Layout/Tab:', - ' Exclude:', - " - 'example2.rb'", - '', '# Offense count: 3', '# Cop supports --auto-correct.', '# Configuration parameters: AllowInHeredoc.', @@ -784,15 +784,15 @@ def a; end '', '# Offense count: 1', '# Cop supports --auto-correct.', - 'Layout/InitialIndentation:', + '# Configuration parameters: IndentationWidth, EnforcedStyle.', + '# SupportedStyles: spaces, tabs', + 'Layout/IndentationStyle:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', - '# Configuration parameters: IndentationWidth, EnforcedStyle.', - '# SupportedStyles: spaces, tabs', - 'Layout/Tab:', + 'Layout/InitialIndentation:', ' Exclude:', " - 'example2.rb'"] actual = IO.read('.rubocop_todo.yml').split($RS) @@ -899,6 +899,13 @@ def a; end " - 'example2.rb'", '', '# Cop supports --auto-correct.', + '# Configuration parameters: IndentationWidth, EnforcedStyle.', + '# SupportedStyles: spaces, tabs', + 'Layout/IndentationStyle:', + ' Exclude:', + " - 'example2.rb'", + '', + '# Cop supports --auto-correct.', 'Layout/InitialIndentation:', ' Exclude:', " - 'example2.rb'", @@ -912,13 +919,6 @@ def a; end " - 'example1.rb'", '', '# Cop supports --auto-correct.', - '# Configuration parameters: IndentationWidth, EnforcedStyle.', - '# SupportedStyles: spaces, tabs', - 'Layout/Tab:', - ' Exclude:', - " - 'example2.rb'", - '', - '# Cop supports --auto-correct.', '# Configuration parameters: AllowInHeredoc.', 'Layout/TrailingWhitespace:', ' Exclude:', diff --git a/spec/rubocop/cli/cli_options_spec.rb b/spec/rubocop/cli/cli_options_spec.rb index 92661f8e115..043a4fe157c 100644 --- a/spec/rubocop/cli/cli_options_spec.rb +++ b/spec/rubocop/cli/cli_options_spec.rb @@ -431,7 +431,7 @@ class SomeCop < Cop 'end']) expect(cli.run(['--format', 'simple', '--only', - 'Style/IfUnlessModifier,Layout/Tab,' \ + 'Style/IfUnlessModifier,Layout/IndentationStyle,' \ 'Layout/SpaceAroundOperators', 'example.rb'])).to eq(1) expect($stderr.string).to eq('') @@ -439,7 +439,7 @@ class SomeCop < Cop == example.rb == C: 1: 1: Style/IfUnlessModifier: Favor modifier if usage when having a single-line body. Another good alternative is the usage of control flow &&/||. C: 1: 5: Layout/SpaceAroundOperators: Surrounding space missing for operator ==. - C: 2: 1: Layout/Tab: Tab detected. + C: 2: 1: Layout/IndentationStyle: Tab detected in indentation. 1 file inspected, 3 offenses detected RESULT @@ -454,15 +454,14 @@ class SomeCop < Cop Layout/EndAlignment: Enabled: false YAML - expect(cli.run(['--format', 'simple', - '--only', 'Layout/Tab,Layout/SpaceAroundOperators', - '--lint', - 'example.rb'])).to eq(1) + expect(cli.run(['--format', 'simple', '--only', + 'Layout/IndentationStyle,Layout/SpaceAroundOperators', + '--lint', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(<<~RESULT) == example.rb == C: 1: 5: Layout/SpaceAroundOperators: Surrounding space missing for operator ==. - C: 2: 1: Layout/Tab: Tab detected. + C: 2: 1: Layout/IndentationStyle: Tab detected in indentation. W: 2: 2: Lint/UselessAssignment: Useless assignment to variable - y. 1 file inspected, 3 offenses detected @@ -481,10 +480,10 @@ class SomeCop < Cop expect($stdout.string).to eq(<<~RESULT) 1 Layout/CommentIndentation + 1 Layout/IndentationStyle 1 Layout/IndentationWidth 1 Layout/LineLength 1 Layout/SpaceAroundOperators - 1 Layout/Tab 1 Layout/TrailingWhitespace -- 6 Total @@ -509,9 +508,9 @@ class SomeCop < Cop .to eq(<<~RESULT) 1 Layout/CommentIndentation + 1 Layout/IndentationStyle 1 Layout/IndentationWidth 1 Layout/LineLength - 1 Layout/Tab 1 Layout/TrailingWhitespace 1 Style/FrozenStringLiteralComment 1 Style/NumericLiterals @@ -574,9 +573,9 @@ class SomeCop < Cop expect($stdout.string) .to eq(<<~RESULT) + 1 Layout/IndentationStyle 1 Layout/IndentationWidth 1 Layout/SpaceAroundOperators - 1 Layout/Tab 1 Layout/TrailingWhitespace 1 Migration/DepartmentName 1 Style/FrozenStringLiteralComment @@ -618,7 +617,7 @@ class SomeCop < Cop 'end # rubocop:disable all']) expect(cli.run(['--format', 'offenses', '--except', - 'Style/IfUnlessModifier,Layout/Tab,' \ + 'Style/IfUnlessModifier,Layout/IndentationStyle,' \ "Layout/SpaceAroundOperators,#{cop_name}", 'example.rb'])).to eq(1) if cop_name == 'RedundantCopDisableDirective' @@ -644,10 +643,11 @@ class SomeCop < Cop describe '--lint' do it 'runs only lint cops' do - create_file('example.rb', ['if 0 ', - "\ty", - "\tz # rubocop:disable Layout/Tab", - 'end']) + create_file('example.rb', + ['if 0 ', + "\ty", + "\tz # rubocop:disable Layout/IndentationStyle", + 'end']) # IfUnlessModifier depends on the configuration of LineLength. expect(cli.run(['--format', 'simple', '--lint', @@ -914,12 +914,12 @@ def full_description_of_cop(cop) end context 'with one cop given' do - let(:arguments) { ['Layout/Tab'] } + let(:arguments) { ['Layout/IndentationStyle'] } it 'prints that cop and nothing else' do expect(stdout).to match( ['# Supports --auto-correct', - 'Layout/Tab:', + 'Layout/IndentationStyle:', ' Description: Consistent indentation either with tabs only or spaces only.', # rubocop:disable Layout/LineLength /^ StyleGuide: ('|")#spaces-indentation('|")$/, ' Enabled: true', @@ -933,18 +933,18 @@ def full_description_of_cop(cop) end context 'with two cops given' do - let(:arguments) { ['Layout/Tab,Layout/LineLength'] } + let(:arguments) { ['Layout/IndentationStyle,Layout/LineLength'] } include_examples 'prints config' end context 'with one of the cops misspelled' do - let(:arguments) { ['Layout/Tab,Lint/X123'] } + let(:arguments) { ['Layout/IndentationStyle,Lint/X123'] } it 'skips the unknown cop' do expect(stdout).to match( ['# Supports --auto-correct', - 'Layout/Tab:', + 'Layout/IndentationStyle:', ' Description: Consistent indentation either with tabs only or spaces only.', # rubocop:disable Layout/LineLength /^ StyleGuide: ('|")#spaces-indentation('|")$/, ' Enabled: true'].join("\n") @@ -1085,7 +1085,8 @@ def badName 'Incorrect indentation detected (column 0 instead of 1).', '# frozen_string_literal: true', '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^', - 'example2.rb:3:1: C: Layout/Tab: Tab detected.', + 'example2.rb:3:1: C: Layout/IndentationStyle: '\ + 'Tab detected in indentation.', "\tx", '^', 'example2.rb:3:2: C: Layout/InitialIndentation: ' \ @@ -1149,7 +1150,7 @@ def badName #{abs('example1.rb')}:3:5: C: Layout/TrailingWhitespace: Trailing whitespace detected. #{abs('example1.rb')}:4:2: C: Layout/TrailingWhitespace: Trailing whitespace detected. #{abs('example2.rb')}:1:1: C: Layout/CommentIndentation: Incorrect indentation detected (column 0 instead of 1). - #{abs('example2.rb')}:3:1: C: Layout/Tab: Tab detected. + #{abs('example2.rb')}:3:1: C: Layout/IndentationStyle: Tab detected in indentation. #{abs('example2.rb')}:3:2: C: Layout/InitialIndentation: Indentation of first line in file detected. #{abs('example2.rb')}:4:1: C: Layout/IndentationConsistency: Inconsistent indentation detected. RESULT diff --git a/spec/rubocop/comment_config_spec.rb b/spec/rubocop/comment_config_spec.rb index 8e175fe27d7..1f7711f4449 100644 --- a/spec/rubocop/comment_config_spec.rb +++ b/spec/rubocop/comment_config_spec.rb @@ -33,7 +33,7 @@ '', '# rubocop:enable Lint/Void', '', - '# rubocop:disable Style/For, Style/Not,Layout/Tab', + '# rubocop:disable Style/For, Style/Not,Layout/IndentationStyle', 'foo', # 28 '', 'class One', @@ -45,7 +45,7 @@ ' # rubocop:disable Style/ClassVars', ' @@class_var = 2', 'end', # 38 - '# rubocop:enable Style/Not,Layout/Tab', + '# rubocop:enable Style/Not,Layout/IndentationStyle', '# rubocop:disable Style/Send, Lint/RandOne some comment why', '# rubocop:disable Layout/BlockAlignment some comment why', '# rubocop:enable Style/Send, Layout/BlockAlignment but why?', @@ -76,7 +76,7 @@ def disabled_lines_of_cop(cop) it 'supports enabling/disabling multiple cops in a single directive' do not_disabled_lines = disabled_lines_of_cop('Style/Not') - tab_disabled_lines = disabled_lines_of_cop('Layout/Tab') + tab_disabled_lines = disabled_lines_of_cop('Layout/IndentationStyle') expect(not_disabled_lines).to eq(tab_disabled_lines) expected_part = (27..39).to_a diff --git a/spec/rubocop/cop/generator_spec.rb b/spec/rubocop/cop/generator_spec.rb index 618ea5be1f1..48f12af2534 100644 --- a/spec/rubocop/cop/generator_spec.rb +++ b/spec/rubocop/cop/generator_spec.rb @@ -94,12 +94,13 @@ def on_send(node) end it 'refuses to overwrite existing files' do - new_cop = described_class.new('Layout/Tab', 'your_id') + new_cop = described_class.new('Layout/IndentationStyle', 'your_id') allow(new_cop).to receive(:exit!) expect { new_cop.write_source } .to output( - "rake new_cop: lib/rubocop/cop/layout/tab.rb already exists!\n" + 'rake new_cop: lib/rubocop/cop/layout/indentation_style.rb '\ + "already exists!\n" ).to_stderr end end @@ -142,12 +143,13 @@ def on_send(node) end it 'refuses to overwrite existing files' do - new_cop = described_class.new('Layout/Tab', 'your_id') + new_cop = described_class.new('Layout/IndentationStyle', 'your_id') allow(new_cop).to receive(:exit!) expect { new_cop.write_spec } .to output( - "rake new_cop: spec/rubocop/cop/layout/tab_spec.rb already exists!\n" + 'rake new_cop: spec/rubocop/cop/layout/indentation_style_spec.rb '\ + "already exists!\n" ).to_stderr end end diff --git a/spec/rubocop/cop/layout/tab_spec.rb b/spec/rubocop/cop/layout/indentation_style_spec.rb similarity index 80% rename from spec/rubocop/cop/layout/tab_spec.rb rename to spec/rubocop/cop/layout/indentation_style_spec.rb index ee654ca7a1a..b82a33a4ad1 100644 --- a/spec/rubocop/cop/layout/tab_spec.rb +++ b/spec/rubocop/cop/layout/indentation_style_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe RuboCop::Cop::Layout::Tab do +RSpec.describe RuboCop::Cop::Layout::IndentationStyle do subject(:cop) { described_class.new(config) } let(:config) do @@ -9,55 +9,49 @@ } RuboCop::Config.new( 'Layout/IndentationWidth' => { 'Width' => 2 }, - 'Layout/Tab' => cop_config.merge(supported_styles) + 'Layout/IndentationStyle' => cop_config.merge(supported_styles) ) end - context 'when EnforcedStyle is space' do + context 'when EnforcedStyle is spaces' do let(:cop_config) { { 'EnforcedStyle' => 'spaces' } } it 'registers an offense for a line indented with tab' do expect_offense(<<~RUBY) x = 0 - ^ Tab detected. + ^ Tab detected in indentation. RUBY end it 'registers an offense for a line indented with multiple tabs' do expect_offense(<<~RUBY) x = 0 - ^^^ Tab detected. + ^^^ Tab detected in indentation. RUBY end it 'registers an offense for a line indented with mixed whitespace' do - expect_offense(<<-'RUBY') + expect_offense(<<~'RUBY') x = 0 - ^ Tab detected. + ^^ Tab detected in indentation. RUBY end it 'registers offenses before __END__ but not after' do expect_offense(<<~RUBY) \tx = 0 - ^ Tab detected. + ^ Tab detected in indentation. __END__ \tx = 0 RUBY end - it 'registers an offense for a tab other than indentation' do - expect_offense(<<~RUBY) - foo \t bar - ^ Tab detected. - RUBY + it 'accepts a line with a tab other than indentation' do + expect_no_offenses("foo \t bar") end - it 'registers an offense for tabs between string literals' do - expect_offense(<<~RUBY) - 'foo'\t'bar' - ^ Tab detected. - RUBY + it 'accepts a line with a tab between string literals' do + expect_no_offenses("'foo'\t'bar'") end it 'accepts a line with tab in a string' do @@ -96,9 +90,9 @@ expect(new_source).to eq(" (x = \"\t\")") end - it 'auto-corrects a line with tab other than indentation' do + it 'does not auto-correct a line with tab other than indentation' do new_source = autocorrect_source("foo \t bar") - expect(new_source).to eq('foo bar') + expect(new_source).to eq("foo \t bar") end context 'custom indentation width' do @@ -114,7 +108,7 @@ end end - context 'when EnforcedStyle is tab' do + context 'when EnforcedStyle is tabs' do let(:cop_config) { { 'EnforcedStyle' => 'tabs' } } it 'registers an offense for a line indented with space' do @@ -147,18 +141,12 @@ RUBY end - it 'registers an offense for a tab other than indentation' do - expect_offense(<<~RUBY) - \tfoo \t bar - ^^^ Tab detected outside of indentation. - RUBY + it 'accepts a line a tab other than indentation' do + expect_no_offenses("\tfoo \t bar") end - it 'registers an offense for tabs between string literals' do - expect_offense(<<~RUBY) - 'foo'\t'bar' - ^^ Tab detected outside of indentation. - RUBY + it 'accepts a line with tabs between string literals' do + expect_no_offenses("'foo'\t'bar'") end it 'accepts a line with tab in a string' do @@ -203,9 +191,9 @@ expect(new_source).to eq("\t(x = \"\t\")") end - it 'auto-corrects a line with tab other than indentation' do + it 'does not auto-corrects a line with tab other than indentation' do new_source = autocorrect_source("\tfoo \t bar") - expect(new_source).to eq("\tfoo bar") + expect(new_source).to eq("\tfoo \t bar") end context 'custom indentation width' do diff --git a/spec/rubocop/cop/layout/line_length_spec.rb b/spec/rubocop/cop/layout/line_length_spec.rb index d8e60219539..99c1de8d5bd 100644 --- a/spec/rubocop/cop/layout/line_length_spec.rb +++ b/spec/rubocop/cop/layout/line_length_spec.rb @@ -380,7 +380,7 @@ def method_definition_that_is_just_under_the_line_length_limit(foo) # rubocop:di 'Layout/IndentationWidth' => { 'Width' => 1 }, - 'Layout/Tab' => { + 'Layout/IndentationStyle' => { 'Enabled' => false, 'IndentationWidth' => 2 }, @@ -399,7 +399,7 @@ def method_definition_that_is_just_under_the_line_length_limit(foo) # rubocop:di 'Layout/IndentationWidth' => { 'Width' => 1 }, - 'Layout/Tab' => { + 'Layout/IndentationStyle' => { 'Enabled' => false, 'IndentationWidth' => 2 }, diff --git a/spec/rubocop/cop/lint/redundant_cop_disable_directive_spec.rb b/spec/rubocop/cop/lint/redundant_cop_disable_directive_spec.rb index 9d9d9192f1f..66739fc4d4b 100644 --- a/spec/rubocop/cop/lint/redundant_cop_disable_directive_spec.rb +++ b/spec/rubocop/cop/lint/redundant_cop_disable_directive_spec.rb @@ -410,14 +410,16 @@ class One RuboCop::Cop::Offense.new(:convention, OpenStruct.new(line: 7, column: 0), 'Tab detected.', - 'Layout/Tab') + 'Layout/IndentationStyle') ] end context 'and a comment disables' do context 'that cop' do - let(:source) { '# rubocop:disable Layout/Tab' } - let(:cop_disabled_line_ranges) { { 'Layout/Tab' => [1..100] } } + let(:source) { '# rubocop:disable Layout/IndentationStyle' } + let(:cop_disabled_line_ranges) do + { 'Layout/IndentationStyle' => [1..100] } + end it 'returns an empty array' do expect(cop.offenses.empty?).to be(true) @@ -425,13 +427,19 @@ class One end context 'that cop but on other lines' do - let(:source) { ("\n" * 9) << '# rubocop:disable Layout/Tab' } - let(:cop_disabled_line_ranges) { { 'Layout/Tab' => [10..12] } } + let(:source) do + ("\n" * 9) << '# rubocop:disable Layout/IndentationStyle' + end + let(:cop_disabled_line_ranges) do + { 'Layout/IndentationStyle' => [10..12] } + end it 'returns an offense' do expect(cop.messages) - .to eq(['Unnecessary disabling of `Layout/Tab`.']) - expect(cop.highlights).to eq(['# rubocop:disable Layout/Tab']) + .to eq(['Unnecessary disabling of `Layout/IndentationStyle`.']) + expect(cop.highlights).to eq( + ['# rubocop:disable Layout/IndentationStyle'] + ) end end diff --git a/spec/rubocop/cop/style/if_unless_modifier_spec.rb b/spec/rubocop/cop/style/if_unless_modifier_spec.rb index 449ac58c5ab..e8e1ee8fd58 100644 --- a/spec/rubocop/cop/style/if_unless_modifier_spec.rb +++ b/spec/rubocop/cop/style/if_unless_modifier_spec.rb @@ -499,7 +499,7 @@ def f end end - context 'with disabled Layout/Tab cop' do + context 'with disabled Layout/IndentationStyle cop' do shared_examples 'with tabs indentation' do let(:source) do # Empty lines should make no difference. @@ -542,13 +542,13 @@ def f end end - context 'with Layout/Tab: IndentationWidth config' do + context 'with Layout/IndentationStyle: IndentationWidth config' do let(:config) do RuboCop::Config.new( 'Layout/IndentationWidth' => { 'Width' => 1 }, - 'Layout/Tab' => { + 'Layout/IndentationStyle' => { 'Enabled' => false, 'IndentationWidth' => 2 }, @@ -565,7 +565,7 @@ def f 'Layout/IndentationWidth' => { 'Width' => 1 }, - 'Layout/Tab' => { + 'Layout/IndentationStyle' => { 'Enabled' => false }, 'Layout/LineLength' => { 'Max' => 10 + 6 } # 6 is indentation @@ -578,7 +578,7 @@ def f context 'without any IndentationWidth config' do let(:config) do RuboCop::Config.new( - 'Layout/Tab' => { + 'Layout/IndentationStyle' => { 'Enabled' => false }, 'Layout/LineLength' => { 'Max' => 10 + 12 } # 12 is indentation diff --git a/spec/rubocop/cop/team_spec.rb b/spec/rubocop/cop/team_spec.rb index 6f6cb363f1d..e35795f892a 100644 --- a/spec/rubocop/cop/team_spec.rb +++ b/spec/rubocop/cop/team_spec.rb @@ -206,7 +206,7 @@ def a include_context 'mock console output' before do - allow_any_instance_of(RuboCop::Cop::Layout::Tab) + allow_any_instance_of(RuboCop::Cop::Layout::IndentationStyle) .to receive(:autocorrect).and_return(buggy_correction) create_file(file_path, <<~RUBY) @@ -226,7 +226,7 @@ def foo let(:cause) { StandardError.new('cause') } let(:error_message) do - 'An error occurred while Layout/Tab cop was inspecting ' \ + 'An error occurred while Layout/IndentationStyle cop was inspecting ' \ '/tmp/example.rb:2:0.' end diff --git a/spec/rubocop/yaml_duplication_checker_spec.rb b/spec/rubocop/yaml_duplication_checker_spec.rb index 696b5d160f1..621f63a3f91 100644 --- a/spec/rubocop/yaml_duplication_checker_spec.rb +++ b/spec/rubocop/yaml_duplication_checker_spec.rb @@ -17,10 +17,10 @@ def check(yaml, &block) context 'when yaml has duplicated keys in the top level' do let(:yaml) { <<~YAML } - Layout/Tab: + Layout/IndentationStyle: Enabled: true - Layout/Tab: + Layout/IndentationStyle: Enabled: false YAML @@ -34,8 +34,8 @@ def check(yaml, &block) key1 = key_a key2 = key_b end - expect(key1.value).to eq('Layout/Tab') - expect(key2.value).to eq('Layout/Tab') + expect(key1.value).to eq('Layout/IndentationStyle') + expect(key2.value).to eq('Layout/IndentationStyle') end end @@ -49,15 +49,15 @@ def check(yaml, &block) end expect(key1.start_line).to eq(0) expect(key2.start_line).to eq(3) - expect(key1.value).to eq('Layout/Tab') - expect(key2.value).to eq('Layout/Tab') + expect(key1.value).to eq('Layout/IndentationStyle') + expect(key2.value).to eq('Layout/IndentationStyle') end end end context 'when yaml has duplicated keys in the second level' do let(:yaml) { <<~YAML } - Layout/Tab: + Layout/IndentationStyle: Enabled: true Enabled: false YAML From d95f65f719fd270c2c8b4a96fadf9f8c93f6e9df Mon Sep 17 00:00:00 2001 From: Draco Ater Date: Tue, 14 Apr 2020 08:35:47 +0300 Subject: [PATCH 4/6] Add relnotes and changelog entries. Add renamed cop into RENAMED_COPS. Fix config_obsoletion specs. --- CHANGELOG.md | 6 ++++++ config/default.yml | 2 +- lib/rubocop/config_obsoletion.rb | 1 + relnotes/v0.82.0.md | 9 +++++++++ spec/rubocop/config_obsoletion_spec.rb | 3 +++ 5 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 relnotes/v0.82.0.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 71a25ceefa3..6ce08c731dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,13 @@ ### New features +* [#7867](https://github.com/rubocop-hq/rubocop/issues/7867): Add support for tabs in indentation. ([@DracoAter][]) * [#7850](https://github.com/rubocop-hq/rubocop/issues/7850): Make it possible to enable/disable pending cops. ([@koic][]) +### Changes + +* Renamed `Layout/Tab` cop to `Layout/IndentationStyle` ([@DracoAter][]) + ### Bug fixes * [#7842](https://github.com/rubocop-hq/rubocop/issues/7842): Fix a false positive for `Lint/RaiseException` when raising Exception with explicit namespace. ([@koic][]) @@ -4438,3 +4443,4 @@ [@dmolesUC]: https://github.com/dmolesUC [@yuritomanek]: https://github.com/yuritomanek [@egze]: https://github.com/egze +[@DracoAter]: https:/github.com/DracoAter diff --git a/config/default.yml b/config/default.yml index 66f9a52af5a..a6cccc50360 100644 --- a/config/default.yml +++ b/config/default.yml @@ -806,7 +806,7 @@ Layout/IndentationStyle: StyleGuide: '#spaces-indentation' Enabled: true VersionAdded: '0.49' - VersionChanged: '0.51' + VersionChanged: '0.82' # By default, the indentation width from Layout/IndentationWidth is used # But it can be overridden by setting this parameter # It is used during auto-correction to determine how many spaces should diff --git a/lib/rubocop/config_obsoletion.rb b/lib/rubocop/config_obsoletion.rb index 588714380f1..25d8add4966 100644 --- a/lib/rubocop/config_obsoletion.rb +++ b/lib/rubocop/config_obsoletion.rb @@ -17,6 +17,7 @@ class ConfigObsoletion 'Layout/IndentHash' => 'Layout/FirstHashElementIndentation', 'Layout/IndentHeredoc' => 'Layout/HeredocIndentation', 'Layout/LeadingBlankLines' => 'Layout/LeadingEmptyLines', + 'Layout/Tab' => 'Layout/IndentationStyle', 'Layout/TrailingBlankLines' => 'Layout/TrailingEmptyLines', 'Lint/DuplicatedKey' => 'Lint/DuplicateHashKey', 'Lint/EndInMethod' => 'Style/EndBlock', diff --git a/relnotes/v0.82.0.md b/relnotes/v0.82.0.md new file mode 100644 index 00000000000..1269d425e1c --- /dev/null +++ b/relnotes/v0.82.0.md @@ -0,0 +1,9 @@ +### New features + +* [#7867](https://github.com/rubocop-hq/rubocop/issues/7867): Add support for tabs in indentation. ([@DracoAter][]) + +### Changes + +* Renamed `Layout/Tab` cop to `Layout/IndentationStyle` ([@DracoAter][]) + +[@DracoAter]: https:/github.com/DracoAter diff --git a/spec/rubocop/config_obsoletion_spec.rb b/spec/rubocop/config_obsoletion_spec.rb index 99e8e6e5647..bc2c39452f8 100644 --- a/spec/rubocop/config_obsoletion_spec.rb +++ b/spec/rubocop/config_obsoletion_spec.rb @@ -29,6 +29,7 @@ 'Layout/IndentHash' => { 'Enabled': true }, 'Layout/IndentHeredoc' => { 'Enabled': true }, 'Layout/LeadingBlankLines' => { 'Enabled': true }, + 'Layout/Tab' => { 'Enabled': true }, 'Layout/TrailingBlankLines' => { 'Enabled': true }, 'Lint/DuplicatedKey' => { 'Enabled': true }, 'Lint/HandleExceptions' => { 'Enabled': true }, @@ -108,6 +109,8 @@ (obsolete configuration found in example/.rubocop.yml, please update it) The `Layout/LeadingBlankLines` cop has been renamed to `Layout/LeadingEmptyLines`. (obsolete configuration found in example/.rubocop.yml, please update it) + The `Layout/Tab` cop has been renamed to `Layout/IndentationStyle`. + (obsolete configuration found in example/.rubocop.yml, please update it) The `Layout/TrailingBlankLines` cop has been renamed to `Layout/TrailingEmptyLines`. (obsolete configuration found in example/.rubocop.yml, please update it) The `Lint/DuplicatedKey` cop has been renamed to `Lint/DuplicateHashKey`. From d6cdf0b3fbdb7ee77e5bfa2101cba89e09e28f96 Mon Sep 17 00:00:00 2001 From: Draco Ater Date: Tue, 14 Apr 2020 08:42:29 +0300 Subject: [PATCH 5/6] Merge master. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ae576c2ec1..c8c7b0aa97c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4454,7 +4454,7 @@ [@dmolesUC]: https://github.com/dmolesUC [@yuritomanek]: https://github.com/yuritomanek [@egze]: https://github.com/egze -[@DracoAter]: https:/github.com/DracoAter [@rafaelfranca]: https://github.com/rafaelfranca [@knu]: https://github.com/knu [@saurabhmaurya15]: https://github.com/saurabhmaurya15 +[@DracoAter]: https:/github.com/DracoAter From b8c2b445e911bb1fbcef6ea39f19221bca21f2cb Mon Sep 17 00:00:00 2001 From: Draco Ater Date: Tue, 14 Apr 2020 09:01:29 +0300 Subject: [PATCH 6/6] Fix changelog entries. --- CHANGELOG.md | 4 ++-- manual/cops_layout.md | 2 +- relnotes/v0.82.0.md | 9 --------- 3 files changed, 3 insertions(+), 12 deletions(-) delete mode 100644 relnotes/v0.82.0.md diff --git a/CHANGELOG.md b/CHANGELOG.md index c8c7b0aa97c..461b10bf123 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### New features -* [#7867](https://github.com/rubocop-hq/rubocop/issues/7867): Add support for tabs in indentation. ([@DracoAter][]) +* [#7867](https://github.com/rubocop-hq/rubocop/pull/7867): Add support for tabs in indentation. ([@DracoAter][]) * [#7863](https://github.com/rubocop-hq/rubocop/issues/7863): Corrector now accepts nodes in addition to ranges. ([@marcandre][]) * [#7862](https://github.com/rubocop-hq/rubocop/issues/7862): Corrector now has a `wrap` method. ([@marcandre][]) * [#7850](https://github.com/rubocop-hq/rubocop/issues/7850): Make it possible to enable/disable pending cops. ([@koic][]) @@ -15,7 +15,7 @@ ### Changes -* Renamed `Layout/Tab` cop to `Layout/IndentationStyle` ([@DracoAter][]) +* **(Breaking)** Renamed `Layout/Tab` cop to `Layout/IndentationStyle`. ([@DracoAter][]) ### Bug fixes diff --git a/manual/cops_layout.md b/manual/cops_layout.md index ea21e32cc32..f02038a6663 100644 --- a/manual/cops_layout.md +++ b/manual/cops_layout.md @@ -2724,7 +2724,7 @@ EnforcedStyle | `normal` | `normal`, `indented_internal_methods` Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged --- | --- | --- | --- | --- -Enabled | Yes | Yes | 0.49 | 0.51 +Enabled | Yes | Yes | 0.49 | 0.82 This cop checks that the indentation method is consistent. Either tabs only or spaces only are used for indentation. diff --git a/relnotes/v0.82.0.md b/relnotes/v0.82.0.md deleted file mode 100644 index 1269d425e1c..00000000000 --- a/relnotes/v0.82.0.md +++ /dev/null @@ -1,9 +0,0 @@ -### New features - -* [#7867](https://github.com/rubocop-hq/rubocop/issues/7867): Add support for tabs in indentation. ([@DracoAter][]) - -### Changes - -* Renamed `Layout/Tab` cop to `Layout/IndentationStyle` ([@DracoAter][]) - -[@DracoAter]: https:/github.com/DracoAter