Skip to content

Commit

Permalink
Add IndentFirstArgument and IndentFirstParameter (rubocop#6982)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxh authored and bbatsov committed Apr 27, 2019
1 parent 7177e98 commit c3a0f96
Show file tree
Hide file tree
Showing 12 changed files with 832 additions and 274 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Add new `Layout/HeredocArgumentClosingParenthesis` cop. ([@maxh][])
* [#6895](https://github.com/rubocop-hq/rubocop/pull/6895): Add support for XDG config home for user-config. ([@Mange][], [@tejasbubane][])
* Add initial autocorrection support to `Metrics/LineLength`. ([@maxh][])
* Add `Layout/IndentFirstParameter`. ([@maxh][])
* [#6974](https://github.com/rubocop-hq/rubocop/issues/6974): Make `Layout/FirstMethodArgumentLineBreak` aware of calling using `super`. ([@koic][])

### Bug fixes
Expand Down Expand Up @@ -36,6 +37,7 @@
* Add `--auto-gen-only-exclude` to the command outputted in `rubocop_todo.yml` if the option is specified. ([@dvandersluis][])
* [#6887](https://github.com/rubocop-hq/rubocop/pull/6887): Allow `Lint/UnderscorePrefixedVariableName` cop to be configured to allow use of block keyword args. ([@dduugg][])
* [#6885](https://github.com/rubocop-hq/rubocop/pull/6885): Revert adding psych >= 3.1 as runtime dependency. ([@andreaseger][])
* Rename `Layout/FirstParameterIndentation` to `Layout/IndentFirstArgument`. ([@maxh][])
* Extract method call argument alignment behavior from `Layout/AlignParameters` into `Layout/AlignArguments`. ([@maxh][])

## 0.67.2 (2019-04-05)
Expand Down
64 changes: 39 additions & 25 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -645,31 +645,6 @@ Layout/FirstMethodParameterLineBreak:
Enabled: false
VersionAdded: '0.49'

Layout/FirstParameterIndentation:
Description: 'Checks the indentation of the first parameter in a method call.'
Enabled: true
VersionAdded: '0.49'
VersionChanged: '0.56'
EnforcedStyle: special_for_inner_method_call_in_parentheses
SupportedStyles:
# The first parameter should always be indented one step more than the
# preceding line.
- consistent
# The first parameter should always be indented one level relative to the
# parent that is receiving the parameter
- consistent_relative_to_receiver
# The first parameter should normally be indented one step more than the
# preceding line, but if it's a parameter for a method call that is itself
# a parameter in a method call, then the inner parameter should be indented
# relative to the inner method.
- special_for_inner_method_call
# Same as `special_for_inner_method_call` except that the special rule only
# applies if the outer method call encloses its arguments in parentheses.
- special_for_inner_method_call_in_parentheses
# By default, the indentation width from `Layout/IndentationWidth` is used
# But it can be overridden by setting this parameter
IndentationWidth: ~

Layout/HeredocArgumentClosingParenthesis:
Description: >-
Checks for the placement of the closing parenthesis in a
Expand Down Expand Up @@ -713,6 +688,45 @@ Layout/IndentAssignment:
# But it can be overridden by setting this parameter
IndentationWidth: ~

Layout/IndentFirstArgument:
Description: 'Checks the indentation of the first argument in a method call.'
Enabled: true
VersionAdded: '0.68'
EnforcedStyle: special_for_inner_method_call_in_parentheses
SupportedStyles:
# The first parameter should always be indented one step more than the
# preceding line.
- consistent
# The first parameter should always be indented one level relative to the
# parent that is receiving the parameter
- consistent_relative_to_receiver
# The first parameter should normally be indented one step more than the
# preceding line, but if it's a parameter for a method call that is itself
# a parameter in a method call, then the inner parameter should be indented
# relative to the inner method.
- special_for_inner_method_call
# Same as `special_for_inner_method_call` except that the special rule only
# applies if the outer method call encloses its arguments in parentheses.
- special_for_inner_method_call_in_parentheses
# By default, the indentation width from `Layout/IndentationWidth` is used
# But it can be overridden by setting this parameter
IndentationWidth: ~

Layout/IndentFirstParameter:
Description: >-
Checks the indentation of the first parameter in a
method defintion.
Enabled: true
VersionAdded: '0.49'
VersionChanged: '0.68'
EnforcedStyle: special_for_inner_method_call_in_parentheses
SupportedStyles:
- consistent
- align_parentheses
# By default, the indentation width from `Layout/IndentationWidth` is used
# But it can be overridden by setting this parameter
IndentationWidth: ~

Layout/IndentHash:
Description: 'Checks the indentation of the first key in a hash literal.'
Enabled: true
Expand Down
5 changes: 3 additions & 2 deletions lib/rubocop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@
require_relative 'rubocop/cop/variable_force/variable_table'

require_relative 'rubocop/cop/mixin/annotation_comment'
require_relative 'rubocop/cop/mixin/array_hash_indentation'
require_relative 'rubocop/cop/mixin/array_min_size'
require_relative 'rubocop/cop/mixin/array_syntax'
require_relative 'rubocop/cop/mixin/alignment'
Expand Down Expand Up @@ -123,6 +122,7 @@
require_relative 'rubocop/cop/mixin/method_complexity'
require_relative 'rubocop/cop/mixin/method_preference'
require_relative 'rubocop/cop/mixin/min_body_length'
require_relative 'rubocop/cop/mixin/multiline_element_indentation'
require_relative 'rubocop/cop/mixin/multiline_element_line_breaks'
require_relative 'rubocop/cop/mixin/multiline_expression_indentation'
require_relative 'rubocop/cop/mixin/multiline_literal_brace_layout'
Expand Down Expand Up @@ -215,12 +215,13 @@
require_relative 'rubocop/cop/layout/first_hash_element_line_break'
require_relative 'rubocop/cop/layout/first_method_argument_line_break'
require_relative 'rubocop/cop/layout/first_method_parameter_line_break'
require_relative 'rubocop/cop/layout/first_parameter_indentation'
require_relative 'rubocop/cop/layout/heredoc_argument_closing_parenthesis'
require_relative 'rubocop/cop/layout/indent_array'
require_relative 'rubocop/cop/layout/indent_assignment'
require_relative 'rubocop/cop/layout/indentation_consistency'
require_relative 'rubocop/cop/layout/indentation_width'
require_relative 'rubocop/cop/layout/indent_first_argument'
require_relative 'rubocop/cop/layout/indent_first_parameter'
require_relative 'rubocop/cop/layout/indent_hash'
require_relative 'rubocop/cop/layout/indent_heredoc'
require_relative 'rubocop/cop/layout/initial_indentation'
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/layout/indent_array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ module Layout
class IndentArray < Cop
include Alignment
include ConfigurableEnforcedStyle
include ArrayHashIndentation
include MultilineElementIndentation

MSG = 'Use %<configured_indentation_width>d spaces for indentation ' \
'in an array, relative to %<base_description>s.'.freeze
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ module RuboCop
module Cop
# rubocop:disable Metrics/LineLength
module Layout
# This cop checks the indentation of the first parameter in a method call.
# Parameters after the first one are checked by Layout/AlignParameters,
# not by this cop.
# This cop checks the indentation of the first argument in a method call
# or definition.
#
# @example
#
Expand All @@ -33,7 +32,7 @@ module Layout
# second_param
#
# @example EnforcedStyle: consistent
# # The first parameter should always be indented one step more than the
# # The first argument should always be indented one step more than the
# # preceding line.
#
# # good
Expand All @@ -59,8 +58,8 @@ module Layout
# second_param
#
# @example EnforcedStyle: consistent_relative_to_receiver
# # The first parameter should always be indented one level relative to
# # the parent that is receiving the parameter
# # The first argument should always be indented one level relative to
# # the parent that is receiving the argument
#
# # good
# some_method(
Expand All @@ -85,9 +84,9 @@ module Layout
# second_params
#
# @example EnforcedStyle: special_for_inner_method_call
# # The first parameter should normally be indented one step more than
# # the preceding line, but if it's a parameter for a method call that
# # is itself a parameter in a method call, then the inner parameter
# # The first argument should normally be indented one step more than
# # the preceding line, but if it's a argument for a method call that
# # is itself a argument in a method call, then the inner argument
# # should be indented relative to the inner method.
#
# # good
Expand Down Expand Up @@ -139,13 +138,13 @@ module Layout
# nested_first_param),
# second_param
#
class FirstParameterIndentation < Cop
class IndentFirstArgument < Cop
# rubocop:enable Metrics/LineLength
include Alignment
include ConfigurableEnforcedStyle
include RangeHelp

MSG = 'Indent the first parameter one step more than %<base>s.'.freeze
MSG = 'Indent the first argument one step more than %<base>s.'.freeze

def on_send(node)
return if !node.arguments? || node.operator_method?
Expand All @@ -163,7 +162,7 @@ def autocorrect(node)
private

def message(arg_node)
return 'Bad indentation of the first parameter.' unless arg_node
return 'Bad indentation of the first argument.' unless arg_node

send_node = arg_node.parent
text = base_range(send_node, arg_node).source.strip
Expand Down
96 changes: 96 additions & 0 deletions lib/rubocop/cop/layout/indent_first_parameter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Layout
# This cop checks the indentation of the first parameter in a method call.
# Parameters after the first one are checked by Layout/AlignParameters,
# not by this cop.
#
# @example
#
# # bad
# def some_method(
# first_param,
# second_param)
# 123
# end
#
# @example EnforcedStyle: consistent
# # The first parameter should always be indented one step more than the
# # preceding line.
#
# # good
# def some_method(
# first_param,
# second_param)
# 123
# end
#
# @example EnforcedStyle: align_parentheses
# # The first parameter should always be indented one step more than the
# # opening parenthesis.
#
# # good
# def some_method(
# first_param,
# second_param)
# 123
# end
class IndentFirstParameter < Cop
include Alignment
include ConfigurableEnforcedStyle
include MultilineElementIndentation

MSG = 'Use %<configured_indentation_width>d spaces for indentation ' \
'in method args, relative to %<base_description>s.'.freeze

def on_def(node)
return if node.arguments.empty?
return if node.arguments.loc.begin.nil?

check(node)
end
alias on_defs on_def

def autocorrect(node)
AlignmentCorrector.correct(processed_source, node, @column_delta)
end

private

def brace_alignment_style
:align_parentheses
end

def check(def_node)
return if ignored_node?(def_node)

left_parenthesis = def_node.arguments.loc.begin
first_elem = def_node.arguments.first
return unless first_elem
return if first_elem.source_range.line == left_parenthesis.line

check_first(first_elem, left_parenthesis, nil, 0)
end

# Returns the description of what the correct indentation is based on.
def base_description(_)
if style == brace_alignment_style
'the position of the opening parenthesis'
else
'the start of the line where the left parenthesis is'
end
end

def message(base_description)
format(
MSG,
configured_indentation_width: configured_indentation_width,
base_description: base_description
)
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/rubocop/cop/layout/indent_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ module Layout
class IndentHash < Cop
include Alignment
include ConfigurableEnforcedStyle
include ArrayHashIndentation
include MultilineElementIndentation

MSG = 'Use %<configured_indentation_width>d spaces for indentation ' \
'in a hash, relative to %<base_description>s.'.freeze
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

module RuboCop
module Cop
# Common code for indenting literal arrays and hashes.
module ArrayHashIndentation
# Common code for indenting the first elements in multiline
# array literals, hash literals, and method definitions.
module MultilineElementIndentation
private

def each_argument_node(node, type)
Expand Down
3 changes: 2 additions & 1 deletion manual/cops.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,11 @@ In the following section you find all available cops:
* [Layout/FirstHashElementLineBreak](cops_layout.md#layoutfirsthashelementlinebreak)
* [Layout/FirstMethodArgumentLineBreak](cops_layout.md#layoutfirstmethodargumentlinebreak)
* [Layout/FirstMethodParameterLineBreak](cops_layout.md#layoutfirstmethodparameterlinebreak)
* [Layout/FirstParameterIndentation](cops_layout.md#layoutfirstparameterindentation)
* [Layout/HeredocArgumentClosingParenthesis](cops_layout.md#layoutheredocargumentclosingparenthesis)
* [Layout/IndentArray](cops_layout.md#layoutindentarray)
* [Layout/IndentAssignment](cops_layout.md#layoutindentassignment)
* [Layout/IndentFirstArgument](cops_layout.md#layoutindentfirstargument)
* [Layout/IndentFirstParameter](cops_layout.md#layoutindentfirstparameter)
* [Layout/IndentHash](cops_layout.md#layoutindenthash)
* [Layout/IndentHeredoc](cops_layout.md#layoutindentheredoc)
* [Layout/IndentationConsistency](cops_layout.md#layoutindentationconsistency)
Expand Down

0 comments on commit c3a0f96

Please sign in to comment.