Skip to content

Commit

Permalink
Support in pattern syntax for Layout/CaseIndentation
Browse files Browse the repository at this point in the history
This PR supports Ruby 2.7's `in` pattern syntax for `Layout/CaseIndentation`.
It is extending `Layout/CaseIndentation` cop because I think it's expected
that the indentation layout will be the same for `case ... when` and `case ... in`.
  • Loading branch information
koic authored and bbatsov committed May 25, 2021
1 parent 428e554 commit 4216c38
Show file tree
Hide file tree
Showing 4 changed files with 741 additions and 288 deletions.
@@ -0,0 +1 @@
* [#9818](https://github.com/rubocop/rubocop/pull/9818): Support Ruby 2.7's `in` pattern syntax for `Layout/CaseIndentation`. ([@koic][])
3 changes: 2 additions & 1 deletion config/default.yml
Expand Up @@ -377,10 +377,11 @@ Layout/BlockEndNewline:
VersionAdded: '0.49'

Layout/CaseIndentation:
Description: 'Indentation of when in a case/when/[else/]end.'
Description: 'Indentation of when in a case/(when|in)/[else/]end.'
StyleGuide: '#indent-when-to-case'
Enabled: true
VersionAdded: '0.49'
VersionChanged: '<<next>>'
EnforcedStyle: case
SupportedStyles:
- case
Expand Down
66 changes: 57 additions & 9 deletions lib/rubocop/cop/layout/case_indentation.rb
Expand Up @@ -3,10 +3,10 @@
module RuboCop
module Cop
module Layout
# This cop checks how the ``when``s of a `case` expression
# This cop checks how the `when` and `in`s of a `case` expression
# are indented in relation to its `case` or `end` keyword.
#
# It will register a separate offense for each misaligned `when`.
# It will register a separate offense for each misaligned `when` and `in`.
#
# @example
# # If Layout/EndAlignment is set to keyword style (default)
Expand All @@ -22,6 +22,13 @@ module Layout
# y / 3
# end
#
# case n
# in pattern
# x * 2
# else
# y / 3
# end
#
# # good for all styles
# case n
# when 0
Expand All @@ -30,6 +37,13 @@ module Layout
# y / 3
# end
#
# case n
# in pattern
# x * 2
# else
# y / 3
# end
#
# @example EnforcedStyle: case (default)
# # if EndAlignment is set to other style such as
# # start_of_line (as shown below), then *when* alignment
Expand All @@ -43,6 +57,13 @@ module Layout
# y / 3
# end
#
# a = case n
# in pattern
# x * 2
# else
# y / 3
# end
#
# # good
# a = case n
# when 0
Expand All @@ -51,6 +72,13 @@ module Layout
# y / 3
# end
#
# a = case n
# in pattern
# x * 2
# else
# y / 3
# end
#
# @example EnforcedStyle: end
# # bad
# a = case n
Expand All @@ -60,37 +88,57 @@ module Layout
# y / 3
# end
#
# a = case n
# in pattern
# x * 2
# else
# y / 3
# end
#
# # good
# a = case n
# when 0
# x * 2
# else
# y / 3
# end
#
# a = case n
# in pattern
# x * 2
# else
# y / 3
# end
class CaseIndentation < Base
include Alignment
include ConfigurableEnforcedStyle
include RangeHelp
extend AutoCorrector

MSG = 'Indent `when` %<depth>s `%<base>s`.'
MSG = 'Indent `%<branch_type>s` %<depth>s `%<base>s`.'

def on_case(case_node)
return if case_node.single_line?

case_node.each_when { |when_node| check_when(when_node) }
case_node.each_when { |when_node| check_when(when_node, 'when') }
end

def on_case_match(case_match_node)
return if case_match_node.single_line?

case_match_node.each_in_pattern { |in_pattern_node| check_when(in_pattern_node, 'in') }
end

private

def check_when(when_node)
def check_when(when_node, branch_type)
when_column = when_node.loc.keyword.column
base_column = base_column(when_node.parent, style)

if when_column == base_column + indentation_width
correct_style_detected
else
incorrect_style(when_node)
incorrect_style(when_node, branch_type)
end
end

Expand All @@ -102,9 +150,9 @@ def indentation_width
indent_one_step? ? configured_indentation_width : 0
end

def incorrect_style(when_node)
def incorrect_style(when_node, branch_type)
depth = indent_one_step? ? 'one step more than' : 'as deep as'
message = format(MSG, depth: depth, base: style)
message = format(MSG, branch_type: branch_type, depth: depth, base: style)

add_offense(when_node.loc.keyword, message: message) do |corrector|
detect_incorrect_style(when_node)
Expand Down Expand Up @@ -141,7 +189,7 @@ def whitespace_range(node)
end

def replacement(node)
case_node = node.each_ancestor(:case).first
case_node = node.each_ancestor(:case, :case_match).first
base_type = cop_config[style_parameter_name] == 'end' ? :end : :case

column = base_column(case_node, base_type)
Expand Down

0 comments on commit 4216c38

Please sign in to comment.