Module: RuboCop::Cop::Style::MethodCallWithArgsParentheses::OmitParentheses
| Relationships & Source Files | |
| Extension / Inclusion / Inheritance Descendants | |
|
Included In:
| |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
|
|
| Defined in: | lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb |
Overview
Style omit_parentheses rubocop:disable-next Metrics/ModuleLength, Metrics/CyclomaticComplexity
Constant Summary
-
OMIT_MSG =
private
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 14'Omit parentheses for method calls with arguments.' -
TRAILING_WHITESPACE_REGEX =
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 13/\s+\Z/.freeze
::RuboCop::Cop::RangeHelp - Included
::RuboCop::Cop::ReparsedEquivalence - Included
Instance Method Summary
- #on_investigation_end
- #allowed_camel_case_method_call?(node) ⇒ Boolean private
- #allowed_chained_call_with_parentheses?(node) ⇒ Boolean private
- #allowed_multiline_call_with_parentheses?(node) ⇒ Boolean private
- #allowed_string_interpolation_method_call?(node) ⇒ Boolean private
- #ambiguous_literal?(node) ⇒ Boolean private
- #ambiguous_range_argument?(node) ⇒ Boolean private
- #apply_reparse_correction(corrector, node) private
- #assigned_before?(node, target) ⇒ Boolean private
- #assignment_in_condition?(node) ⇒ Boolean private
- #autocorrect(corrector, node) private
- #call_as_argument_or_chain?(node) ⇒ Boolean private
- #call_in_argument_with_block?(node) ⇒ Boolean private
- #call_in_literals?(node) ⇒ Boolean private
- #call_in_logical_operators?(node) ⇒ Boolean private
- #call_in_match_pattern?(node) ⇒ Boolean private
- #call_in_optional_arguments?(node) ⇒ Boolean private
- #call_in_single_line_inheritance?(node) ⇒ Boolean private
-
#call_with_ambiguous_arguments?(node) ⇒ Boolean
private
rubocop:disable-next Metrics/PerceivedComplexity.
- #call_with_braced_block?(node) ⇒ Boolean private
- #code_after_closing_parenthesis_on_its_own_line?(node) ⇒ Boolean private
- #command_assignment_before_keyword_operator?(node) ⇒ Boolean private
-
#command_assignment_in_expression?(node) ⇒ Boolean
private
rubocop:disable-next Metrics/PerceivedComplexity.
-
#comment_before_first_argument?(node) ⇒ Boolean
private
Without the parentheses, a comment before the first argument would end the call there, and a line continuation can’t carry the call past a comment.
- #forwards_anonymous_rest_arguments?(node) ⇒ Boolean private
- #hash_literal?(node) ⇒ Boolean private
- #hash_literal_in_arguments?(node) ⇒ Boolean private
- #inside_endless_method_def?(node) ⇒ Boolean private
- #inside_string_interpolation?(node) ⇒ Boolean private
-
#last_expression?(node) ⇒ Boolean
private
Require hash value omission be enclosed in parentheses to prevent the following issue: https://bugs.ruby-lang.org/issues/18396.
-
#legitimate_call_with_parentheses?(node) ⇒ Boolean
private
Metrics/PerceivedComplexity.
- #logical_operator?(node) ⇒ Boolean private
- #method_call_before_constant_resolution?(node) ⇒ Boolean private
- #offense_range(node) private
-
#omit_parentheses(node)
private
Metrics/PerceivedComplexity.
- #outermost_assignment(value) private
- #parentheses_at_the_end_of_multiline_call?(node) ⇒ Boolean private
- #regexp_slash_literal?(node) ⇒ Boolean private
- #require_parentheses_for_hash_value_omission?(node) ⇒ Boolean private
- #splat?(node) ⇒ Boolean private
- #super_call_without_arguments?(node) ⇒ Boolean private
- #syntax_like_method_call?(node) ⇒ Boolean private
- #ternary_if?(node) ⇒ Boolean private
- #trailing_comma?(node) ⇒ Boolean private
- #unary_literal?(node) ⇒ Boolean private
::RuboCop::Cop::ReparsedEquivalence - Included
| #corrected_scope_fragment | The corrections' edits are all contained within the scope, so the corrected fragment can be cut out of the corrected source by adjusting for the edits' length delta. |
| #correction_parses? | Whether the exact correction for |
| #corrections_verify?, #item_range, | |
| #normalize_reparsed_ast | Hook: loosen strict tree equality for corrections that are equivalence-preserving beyond parse identity. |
| #normalized_original, | |
| #parses_equivalently? | Both sides are parsed with the original path so that |
| #preprocess_reparsed_source | Hook: rewrite both sides before parsing. |
| #reparse_scope | The innermost scope that both contains |
| #scope_groups, #verification_too_large?, | |
| #verified_by_reparse | Returns the items whose corrections are verified. |
| #verified_subset | Verifies a group with a single reparse and bisects it when that fails, so a few significant items among many cost a logarithmic number of reparses rather than one each. |
::RuboCop::Cop::RangeHelp - Included
| #add_range, | |
| #arguments_range | A range containing the first to the last argument of a method call or method definition. |
| #column_offset_between, | |
| #contents_range | A range containing only the contents of a literal with delimiters (e.g. |
| #directions, | |
| #effective_column | Returns the column attribute of the range, except if the range is on the first line and there’s a byte order mark at the beginning of that line, in which case 1 is subtracted from the column value. |
| #final_pos | rubocop:disable-next Metrics/ParameterLists. |
| #move_pos, #move_pos_str, #range_between, #range_by_whole_lines, #range_with_comments, #range_with_comments_and_lines, #range_with_surrounding_comma, #range_with_surrounding_space, #source_range | |
Instance Method Details
#allowed_camel_case_method_call?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 100
def allowed_camel_case_method_call?(node) node.camel_case_method? && (node.arguments.none? || cop_config['AllowParenthesesInCamelCaseMethod']) end
#allowed_chained_call_with_parentheses?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 235
def allowed_chained_call_with_parentheses?(node) return false unless cop_config['AllowParenthesesInChaining'] previous = node.descendants.first return false unless previous&.send_type? previous.parenthesized? || allowed_chained_call_with_parentheses?(previous) end
#allowed_multiline_call_with_parentheses?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 231
def allowed_multiline_call_with_parentheses?(node) cop_config['AllowParenthesesInMultilineCall'] && node.multiline? end
#allowed_string_interpolation_method_call?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 105
def allowed_string_interpolation_method_call?(node) cop_config['AllowParenthesesInStringInterpolation'] && inside_string_interpolation?(node) end
#ambiguous_literal?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 244
def ambiguous_literal?(node) splat?(node) || ternary_if?(node) || regexp_slash_literal?(node) || unary_literal?(node) end
#ambiguous_range_argument?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 224
def ambiguous_range_argument?(node) return true if (first_arg = node.first_argument)&.range_type? && first_arg.begin.nil? return true if (last_arg = node.last_argument)&.range_type? && last_arg.end.nil? false end
#apply_reparse_correction(corrector, node) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 50
def apply_reparse_correction(corrector, node) autocorrect(corrector, node) end
#assigned_before?(node, target) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 283
def assigned_before?(node, target) node.assignment? && node.loc.operator.begin < target.source_range.begin end
#assignment_in_condition?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 291
def assignment_in_condition?(node) parent = node.parent return false unless parent grandparent = parent.parent return false unless grandparent parent.assignment? && (grandparent.conditional? || grandparent.when_type?) end
#autocorrect(corrector, node) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 54
def autocorrect(corrector, node) range = args_begin(node) if parentheses_at_the_end_of_multiline_call?(node) # Whitespace after line continuation (`\ `) is a syntax error with_whitespace = range_with_surrounding_space(range, side: :right, newlines: false) corrector.replace(with_whitespace, ' \\') else corrector.replace(range, ' ') end corrector.remove(node.loc.end) end
#call_as_argument_or_chain?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 206
def call_as_argument_or_chain?(node) node.parent&.type?(:call, :super, :yield) && !assigned_before?(node.parent, node) end
#call_in_argument_with_block?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 199
def call_in_argument_with_block?(node) parent = node.parent&.any_block_type? && node.parent.parent return false unless parent parent.type?(:call, :super, :yield) end
#call_in_literals?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 151
def call_in_literals?(node) parent = node.parent&.any_block_type? ? node.parent.parent : node.parent return false unless parent parent.type?(:pair, :array, :range) || splat?(parent) || ternary_if?(parent) end
#call_in_logical_operators?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 160
def call_in_logical_operators?(node) parent = node.parent&.any_block_type? ? node.parent.parent : node.parent return false unless parent if logical_operator?(parent) || command_assignment_before_keyword_operator?(parent) return true end parent.send_type? && parent.arguments.any? do |argument| logical_operator?(argument) end end
#call_in_match_pattern?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 211
def call_in_match_pattern?(node) return false unless (parent = node.parent) parent.any_match_pattern_type? end
#call_in_optional_arguments?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 173
def call_in_optional_arguments?(node) node.parent&.type?(:optarg, :kwoptarg) end
#call_in_single_line_inheritance?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 177
def call_in_single_line_inheritance?(node) node.parent&.class_type? && node.parent.single_line? end
#call_with_ambiguous_arguments?(node) ⇒ Boolean (private)
rubocop:disable-next Metrics/PerceivedComplexity
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 182
def call_with_ambiguous_arguments?(node) call_with_braced_block?(node) || call_in_argument_with_block?(node) || call_as_argument_or_chain?(node) || call_in_match_pattern?(node) || hash_literal_in_arguments?(node) || ambiguous_range_argument?(node) || node.descendants.any? do |n| n.type?(:forwarded_args, :any_block) || ambiguous_literal?(n) || logical_operator?(n) end end
#call_with_braced_block?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 195
def call_with_braced_block?(node) node.type?(:call, :super) && node.block_node&.braces? end
#code_after_closing_parenthesis_on_its_own_line?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 110
def code_after_closing_parenthesis_on_its_own_line?(node) closing = node.loc.end return false if node.arguments.none? || node.last_argument.last_line == closing.line rest = closing.source_line[(closing.column + 1)..].strip !rest.empty? && !rest.start_with?('#') end
#command_assignment_before_keyword_operator?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 260
def command_assignment_before_keyword_operator?(node) return false unless node.assignment? node = node.parent while node.parent&.assignment? return false unless (operator = node.parent) operator.operator_keyword? && operator.semantic_operator? end
#command_assignment_in_expression?(node) ⇒ Boolean (private)
rubocop:disable-next Metrics/PerceivedComplexity
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 302
def command_assignment_in_expression?(node) value = node.parent&.type?(:any_block, :rescue) ? node.parent : node assignment = outermost_assignment(value) return false if assignment.equal?(value) call_in_literals?(assignment) || call_in_logical_operators?(assignment) || call_in_optional_arguments?(assignment) || call_as_argument_or_chain?(assignment) || assignment.parent&.type?(:masgn, :return, :next, :break, :defined?) end
#comment_before_first_argument?(node) ⇒ Boolean (private)
Without the parentheses, a comment before the first argument would end the call there, and a line continuation can’t carry the call past a comment.
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 121
def comment_before_first_argument?(node) return false unless (first_argument = node.first_argument) lines = node.loc.begin.line...first_argument.first_line processed_source.each_comment_in_lines(lines).any? end
#forwards_anonymous_rest_arguments?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 322
def forwards_anonymous_rest_arguments?(node) node.arguments.any? do |argument| next true if argument.forwarded_restarg_type? argument.hash_type? && argument.children.any?(&:forwarded_kwrestarg_type?) end end
#hash_literal?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 269
def hash_literal?(node) node.hash_type? && node.braces? end
#hash_literal_in_arguments?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 217
def hash_literal_in_arguments?(node) node.arguments.any? do |n| hash_literal?(n) || (n.send_type? && node.descendants.any? { |descendant| hash_literal?(descendant) }) end end
#inside_endless_method_def?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 70
def inside_endless_method_def?(node) # parens are required around arguments inside an endless method node.each_ancestor(:any_def).any?(&:endless?) && node.arguments.any? end
#inside_string_interpolation?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 287
def inside_string_interpolation?(node) node.ancestors.drop_while { |a| !a.begin_type? }.any?(&:dstr_type?) end
#last_expression?(node) ⇒ Boolean (private)
Require hash value omission be enclosed in parentheses to prevent the following issue: https://bugs.ruby-lang.org/issues/18396.
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 84
def last_expression?(node) !(node.parent&.assignment? ? node.parent.right_sibling : node.right_sibling) end
#legitimate_call_with_parentheses?(node) ⇒ Boolean (private)
Metrics/PerceivedComplexity
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 136
def legitimate_call_with_parentheses?(node) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity call_in_literals?(node) || node.parent&.when_type? || call_with_ambiguous_arguments?(node) || call_in_logical_operators?(node) || call_in_optional_arguments?(node) || call_in_single_line_inheritance?(node) || allowed_multiline_call_with_parentheses?(node) || allowed_chained_call_with_parentheses?(node) || assignment_in_condition?(node) || command_assignment_in_expression?(node) || forwards_anonymous_rest_arguments?(node) || trailing_comma?(node) end
#logical_operator?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 256
def logical_operator?(node) node.operator_keyword? && node.logical_operator? end
#method_call_before_constant_resolution?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 92
def method_call_before_constant_resolution?(node) node.parent&.const_type? end
#offense_range(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 66
def offense_range(node) node.loc.begin.join(node.loc.end) end
#omit_parentheses(node) (private)
Metrics/PerceivedComplexity
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 33
def omit_parentheses(node) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity return unless node.parenthesized? return if inside_endless_method_def?(node) return if require_parentheses_for_hash_value_omission?(node) return if syntax_like_method_call?(node) return if method_call_before_constant_resolution?(node) return if super_call_without_arguments?(node) return if legitimate_call_with_parentheses?(node) return if allowed_camel_case_method_call?(node) return if allowed_string_interpolation_method_call?(node) return if code_after_closing_parenthesis_on_its_own_line?(node) return if comment_before_first_argument?(node) return if args_parenthesized?(node) (@pending_omit_offenses ||= []) << node end
#on_investigation_end
[ GitHub ]# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 17
def on_investigation_end # Each candidate's exact correction is verified by reparsing before # the offense is registered, so an omission that would change how # the code parses is never reported or offered. verified_by_reparse(@pending_omit_offenses || []).each do |node| add_offense(offense_range(node), message: OMIT_MSG) do |corrector| autocorrect(corrector, node) end end @pending_omit_offenses = [] super end
#outermost_assignment(value) (private)
[ GitHub ]# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 314
def outermost_assignment(value) parent = value.parent return value if !parent&.assignment? || parent.masgn_type? return value unless assigned_before?(parent, value) outermost_assignment(parent) end
#parentheses_at_the_end_of_multiline_call?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 128
def parentheses_at_the_end_of_multiline_call?(node) return false unless node.multiline? opening = node.loc.begin opening.source_line[(opening.column + 1)..].gsub(TRAILING_WHITESPACE_REGEX, '').empty? end
#regexp_slash_literal?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 273
def regexp_slash_literal?(node) node.regexp_type? && node.loc.begin.source == '/' end
#require_parentheses_for_hash_value_omission?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 75
def require_parentheses_for_hash_value_omission?(node) # rubocop:disable Metrics/PerceivedComplexity return false unless (last_argument = node.last_argument) return false if !last_argument.hash_type? || !last_argument.pairs.last&.value_omission? node.parent&.conditional? || node.parent&.single_line? || !last_expression?(node) end
#splat?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 248
def splat?(node) node.type?(:splat, :kwsplat, :block_pass) end
#super_call_without_arguments?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 96
def super_call_without_arguments?(node) node.super_type? && node.arguments.none? end
#syntax_like_method_call?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 88
def syntax_like_method_call?(node) node.implicit_call? || node.operator_method? end
#ternary_if?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 252
def ternary_if?(node) node.if_type? && node.ternary? end
#trailing_comma?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 330
def trailing_comma?(node) return false unless (last_argument = node.last_argument) range = last_argument.source_range.end.join(node.loc.end.begin) processed_source.tokens_within(range).any?(&:comma?) end
#unary_literal?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb', line 277
def unary_literal?(node) return true if node.numeric_type? && node.sign? node.parent&.send_type? && node.parent.unary_operation? end