Skip to content

Commit 6b9510d

Browse files
authored
Add support for tabs in indentation (#7867)
This commit adds SupportedStyles to Layout/Tab - spaces and tabs. It also renames the cop to to Layout/IndentationStyle, as the old name no longer reflects its purpose. One notable difference is that before the `Layout/Tab` cop was warning on tabs anywhere in the source, but now we're focusing only on tabs used for indentation purposes.
1 parent 85ecd05 commit 6b9510d

25 files changed

+446
-248
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### New features
66

7+
* [#7867](https://github.com/rubocop-hq/rubocop/pull/7867): Add support for tabs in indentation. ([@DracoAter][])
78
* [#7863](https://github.com/rubocop-hq/rubocop/issues/7863): Corrector now accepts nodes in addition to ranges. ([@marcandre][])
89
* [#7862](https://github.com/rubocop-hq/rubocop/issues/7862): Corrector now has a `wrap` method. ([@marcandre][])
910
* [#7850](https://github.com/rubocop-hq/rubocop/issues/7850): Make it possible to enable/disable pending cops. ([@koic][])
@@ -12,6 +13,10 @@
1213
* [#7384](https://github.com/rubocop-hq/rubocop/pull/7384): Add new `Style/DisableCopsWithinSourceCodeDirective` cop. ([@egze][])
1314
* [#7826](https://github.com/rubocop-hq/rubocop/issues/7826): Add new `Layout/SpaceAroundMethodCallOperator` cop. ([@saurabhmaurya15][])
1415

16+
### Changes
17+
18+
* **(Breaking)** Renamed `Layout/Tab` cop to `Layout/IndentationStyle`. ([@DracoAter][])
19+
1520
### Bug fixes
1621

1722
* [#7871](https://github.com/rubocop-hq/rubocop/pull/7871): Fix an auto-correction bug in `Lint/BooleanSymbol`. ([@knu][])
@@ -4452,3 +4457,4 @@
44524457
[@rafaelfranca]: https://github.com/rafaelfranca
44534458
[@knu]: https://github.com/knu
44544459
[@saurabhmaurya15]: https://github.com/saurabhmaurya15
4460+
[@DracoAter]: https:/github.com/DracoAter

config/default.yml

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,22 @@ Layout/IndentationConsistency:
801801
# A reference to `EnforcedStyle: indented_internal_methods`.
802802
- https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#follow-the-coding-conventions
803803

804+
Layout/IndentationStyle:
805+
Description: 'Consistent indentation either with tabs only or spaces only.'
806+
StyleGuide: '#spaces-indentation'
807+
Enabled: true
808+
VersionAdded: '0.49'
809+
VersionChanged: '0.82'
810+
# By default, the indentation width from Layout/IndentationWidth is used
811+
# But it can be overridden by setting this parameter
812+
# It is used during auto-correction to determine how many spaces should
813+
# replace each tab.
814+
IndentationWidth: ~
815+
EnforcedStyle: spaces
816+
SupportedStyles:
817+
- spaces
818+
- tabs
819+
804820
Layout/IndentationWidth:
805821
Description: 'Use 2 spaces for indentation.'
806822
StyleGuide: '#spaces-indentation'
@@ -1263,18 +1279,6 @@ Layout/SpaceInsideStringInterpolation:
12631279
- space
12641280
- no_space
12651281

1266-
Layout/Tab:
1267-
Description: 'No hard tabs.'
1268-
StyleGuide: '#spaces-indentation'
1269-
Enabled: true
1270-
VersionAdded: '0.49'
1271-
VersionChanged: '0.51'
1272-
# By default, the indentation width from Layout/IndentationWidth is used
1273-
# But it can be overridden by setting this parameter
1274-
# It is used during auto-correction to determine how many spaces should
1275-
# replace each tab.
1276-
IndentationWidth: ~
1277-
12781282
Layout/TrailingEmptyLines:
12791283
Description: 'Checks trailing blank lines and final newline.'
12801284
StyleGuide: '#newline-eof'

lib/rubocop.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@
235235
require_relative 'rubocop/cop/layout/heredoc_argument_closing_parenthesis'
236236
require_relative 'rubocop/cop/layout/heredoc_indentation'
237237
require_relative 'rubocop/cop/layout/indentation_consistency'
238+
require_relative 'rubocop/cop/layout/indentation_style'
238239
require_relative 'rubocop/cop/layout/indentation_width'
239240
require_relative 'rubocop/cop/layout/initial_indentation'
240241
require_relative 'rubocop/cop/layout/leading_comment_space'
@@ -278,7 +279,6 @@
278279
require_relative 'rubocop/cop/layout/space_inside_range_literal'
279280
require_relative 'rubocop/cop/layout/space_inside_reference_brackets'
280281
require_relative 'rubocop/cop/layout/space_inside_string_interpolation'
281-
require_relative 'rubocop/cop/layout/tab'
282282
require_relative 'rubocop/cop/layout/trailing_empty_lines'
283283
require_relative 'rubocop/cop/layout/trailing_whitespace'
284284

lib/rubocop/config_obsoletion.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class ConfigObsoletion
1717
'Layout/IndentHash' => 'Layout/FirstHashElementIndentation',
1818
'Layout/IndentHeredoc' => 'Layout/HeredocIndentation',
1919
'Layout/LeadingBlankLines' => 'Layout/LeadingEmptyLines',
20+
'Layout/Tab' => 'Layout/IndentationStyle',
2021
'Layout/TrailingBlankLines' => 'Layout/TrailingEmptyLines',
2122
'Lint/DuplicatedKey' => 'Lint/DuplicateHashKey',
2223
'Lint/EndInMethod' => 'Style/EndBlock',

lib/rubocop/cop/badge.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ module RuboCop
44
module Cop
55
# Identifier of all cops containing a department and cop name.
66
#
7-
# All cops are identified by their badge. For example, the badge
8-
# for `RuboCop::Cop::Layout::Tab` is `Layout/Tab`. Badges can be
9-
# parsed as either `Department/CopName` or just `CopName` to allow
10-
# for badge references in source files that omit the department
11-
# for RuboCop to infer.
7+
# All cops are identified by their badge. For example, the badge for
8+
# `RuboCop::Cop::Layout::IndentationStyle` is `Layout/IndentationStyle`.
9+
# Badges can be parsed as either `Department/CopName` or just `CopName` to
10+
# allow for badge references in source files that omit the department for
11+
# RuboCop to infer.
1212
class Badge
1313
# Error raised when a badge parse fails.
1414
class InvalidBadge < Error

lib/rubocop/cop/layout/tab.rb renamed to lib/rubocop/cop/layout/indentation_style.rb

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
module RuboCop
66
module Cop
77
module Layout
8-
# This cop checks for tabs inside the source code.
8+
# This cop checks that the indentation method is consistent.
9+
# Either tabs only or spaces only are used for indentation.
910
#
10-
# @example
11+
# @example EnforcedStyle: spaces (default)
1112
# # bad
1213
# # This example uses a tab to indent bar.
1314
# def foo
@@ -20,17 +21,30 @@ module Layout
2021
# bar
2122
# end
2223
#
23-
class Tab < Cop
24+
# @example EnforcedStyle: tabs
25+
# # bad
26+
# # This example uses spaces to indent bar.
27+
# def foo
28+
# bar
29+
# end
30+
#
31+
# # good
32+
# # This example uses a tab to indent bar.
33+
# def foo
34+
# bar
35+
# end
36+
class IndentationStyle < Cop
2437
include Alignment
38+
include ConfigurableEnforcedStyle
2539
include RangeHelp
2640

27-
MSG = 'Tab detected.'
41+
MSG = '%<type>s detected in indentation.'
2842

2943
def investigate(processed_source)
3044
str_ranges = string_literal_ranges(processed_source.ast)
3145

3246
processed_source.lines.each.with_index(1) do |line, lineno|
33-
match = line.match(/\t+/)
47+
match = find_offence(line)
3448
next unless match
3549

3650
range = source_range(processed_source.buffer,
@@ -43,13 +57,37 @@ def investigate(processed_source)
4357
end
4458

4559
def autocorrect(range)
60+
if range.source.include?("\t")
61+
autocorrect_lambda_for_tabs(range)
62+
else
63+
autocorrect_lambda_for_spaces(range)
64+
end
65+
end
66+
67+
private
68+
69+
def find_offence(line)
70+
if style == :spaces
71+
line.match(/\A\s*\t+/)
72+
else
73+
line.match(/\A\s* +/)
74+
end
75+
end
76+
77+
def autocorrect_lambda_for_tabs(range)
4678
lambda do |corrector|
4779
spaces = ' ' * configured_indentation_width
4880
corrector.replace(range, range.source.gsub(/\t/, spaces))
4981
end
5082
end
5183

52-
private
84+
def autocorrect_lambda_for_spaces(range)
85+
lambda do |corrector|
86+
corrector.replace(range, range.source.gsub(/\A\s+/) do |match|
87+
"\t" * (match.size / configured_indentation_width)
88+
end)
89+
end
90+
end
5391

5492
def in_string_literal?(ranges, tabs_range)
5593
ranges.any? { |range| range.contains?(tabs_range) }
@@ -69,6 +107,10 @@ def string_literal_ranges(ast)
69107
end
70108
end
71109
end
110+
111+
def message(_node)
112+
format(MSG, type: style == :spaces ? 'Tab' : 'Space')
113+
end
72114
end
73115
end
74116
end

lib/rubocop/cop/layout/line_length.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Layout
88
# This cop checks the length of lines in the source code.
99
# The maximum length is configurable.
1010
# The tab size is configured in the `IndentationWidth`
11-
# of the `Layout/Tab` cop.
11+
# of the `Layout/IndentationStyle` cop.
1212
# It also ignores a shebang line by default.
1313
#
1414
# This cop has some autocorrection capabilities.

lib/rubocop/cop/mixin/line_length_help.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def indentation_difference(line)
6363
end
6464

6565
def tab_indentation_width
66-
config.for_cop('Layout/Tab')['IndentationWidth']
66+
config.for_cop('Layout/IndentationStyle')['IndentationWidth']
6767
end
6868

6969
def uri_regexp

lib/rubocop/cop/mixin/statement_modifier.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,13 @@ def max_line_length
5858
end
5959

6060
def indentation_multiplier
61-
return 1 if config.for_cop('Layout/Tab')['Enabled']
61+
return 1 if config.for_cop('Layout/IndentationStyle')['Enabled']
6262

6363
default_configuration = RuboCop::ConfigLoader.default_configuration
64-
config.for_cop('Layout/Tab')['IndentationWidth'] ||
64+
config.for_cop('Layout/IndentationStyle')['IndentationWidth'] ||
6565
config.for_cop('Layout/IndentationWidth')['Width'] ||
66-
default_configuration.for_cop('Layout/Tab')['IndentationWidth'] ||
66+
default_configuration
67+
.for_cop('Layout/IndentationStyle')['IndentationWidth'] ||
6768
default_configuration.for_cop('Layout/IndentationWidth')['Width']
6869
end
6970
end

lib/rubocop/cop/style/if_unless_modifier.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module Style
99
#
1010
# The maximum line length is configured in the `Layout/LineLength`
1111
# cop. The tab size is configured in the `IndentationWidth` of the
12-
# `Layout/Tab` cop.
12+
# `Layout/IndentationStyle` cop.
1313
#
1414
# @example
1515
# # bad

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy