Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add InternalAffairs/NodeFirstOrLastArgument cop #12305

Merged
merged 1 commit into from
Nov 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#12305](https://github.com/rubocop/rubocop/pull/12305): Require `rubocop-ast` version 1.30 or greater. ([@sambostock][])
4 changes: 2 additions & 2 deletions lib/rubocop/cop/bundler/gem_comment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ def contains_checked_options?(node)
end

def gem_options(node)
return [] unless node.arguments.last&.type == :hash
return [] unless node.last_argument&.type == :hash

node.arguments.last.keys.map(&:value)
node.last_argument.keys.map(&:value)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class DeprecatedAttributeAssignment < Base
def on_block(block_node)
return unless gem_specification(block_node)

block_parameter = block_node.arguments.first.source
block_parameter = block_node.first_argument.source

assignment = block_node.descendants.detect do |node|
use_deprecated_attributes?(node, block_parameter)
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop/cop/internal_affairs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
require_relative 'internal_affairs/method_name_end_with'
require_relative 'internal_affairs/method_name_equal'
require_relative 'internal_affairs/node_destructuring'
require_relative 'internal_affairs/node_first_or_last_argument'
require_relative 'internal_affairs/node_matcher_directive'
require_relative 'internal_affairs/node_type_predicate'
require_relative 'internal_affairs/numblock_handler'
Expand Down
53 changes: 53 additions & 0 deletions lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

module RuboCop
module Cop
module InternalAffairs
# Checks for the use of `node.arguments.first` or `node.arguments.last` and
# suggests the use of `node.first_argument` or `node.last_argument` instead.
#
# @example
# # bad
# node.arguments.first
# node.arguments[0]
# node.arguments.last
# node.arguments[-1]
#
# # good
# node.first_argument
# node.last_argument
#
class NodeFirstOrLastArgument < Base
extend AutoCorrector
include RangeHelp

MSG = 'Use `#%<correct>s` instead of `#%<incorrect>s`.'
RESTRICT_ON_SEND = %i[arguments].freeze

# @!method arguments_first_or_last?(node)
def_node_matcher :arguments_first_or_last?, <<~PATTERN
{
(send (send !nil? :arguments) ${:first :last})
(send (send !nil? :arguments) :[] (int ${0 -1}))
}
PATTERN

def on_send(node)
arguments_first_or_last?(node.parent) do |end_or_index|
range = range_between(node.loc.selector.begin_pos, node.parent.source_range.end_pos)
correct = case end_or_index
when :first, 0 then 'first_argument'
when :last, -1 then 'last_argument'
else raise "Unknown end_or_index: #{end_or_index}"
end
message = format(MSG, correct: correct, incorrect: range.source)

add_offense(range, message: message) do |corrector|
corrector.replace(range, correct)
end
end
end
end
end
end
end
4 changes: 2 additions & 2 deletions lib/rubocop/cop/internal_affairs/node_matcher_directive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def on_send(node)
return if node.arguments.none?
return unless valid_method_name?(node)

actual_name = node.arguments.first.value
actual_name = node.first_argument.value
directives = method_directives(node)
return too_many_directives(node) if directives.size > 1

Expand All @@ -53,7 +53,7 @@ def on_send(node)
private

def valid_method_name?(node)
node.arguments.first.str_type? || node.arguments.first.sym_type?
node.first_argument.str_type? || node.first_argument.sym_type?
end

def method_directives(node)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/layout/argument_alignment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def flattened_arguments(node)

def arguments_with_last_arg_pairs(node)
items = node.arguments[0..-2]
last_arg = node.arguments.last
last_arg = node.last_argument

if last_arg.hash_type? && !last_arg.braces?
items += last_arg.pairs
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/layout/first_parameter_indentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def check(def_node)
return if ignored_node?(def_node)

left_parenthesis = def_node.arguments.loc.begin
first_elem = def_node.arguments.first
first_elem = def_node.first_argument
return unless first_elem
return if same_line?(first_elem, left_parenthesis)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def fix_closing_parenthesis(node, corrector)
end

def add_correct_closing_paren(node, corrector)
corrector.insert_after(node.arguments.last, ')')
corrector.insert_after(node.last_argument, ')')
end

def remove_incorrect_closing_paren(node, corrector)
Expand Down Expand Up @@ -271,7 +271,7 @@ def fix_external_trailing_comma(node, corrector)
def add_correct_external_trailing_comma(node, corrector)
return unless external_trailing_comma?(node)

corrector.insert_after(node.arguments.last, ',')
corrector.insert_after(node.last_argument, ',')
end

def remove_incorrect_external_trailing_comma(node, corrector)
Expand Down
6 changes: 3 additions & 3 deletions lib/rubocop/cop/lint/erb_new_arguments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def on_send(node)
private

def autocorrect(corrector, node)
str_arg = node.arguments[0].source
str_arg = node.first_argument.source

kwargs = build_kwargs(node)
overridden_kwargs = override_by_legacy_args(kwargs, node)
Expand All @@ -121,11 +121,11 @@ def correct_arguments?(arguments)
end

def build_kwargs(node)
return [nil, nil] unless node.arguments.last.hash_type?
return [nil, nil] unless node.last_argument.hash_type?

trim_mode_arg, eoutvar_arg = nil

node.arguments.last.pairs.each do |pair|
node.last_argument.pairs.each do |pair|
case pair.key.source
when 'trim_mode'
trim_mode_arg = "trim_mode: #{pair.value.source}"
Expand Down
8 changes: 3 additions & 5 deletions lib/rubocop/cop/lint/non_deterministic_require_order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def on_block_pass(node)
parent_node = node.parent

add_offense(parent_node) do |corrector|
if parent_node.arguments.last&.block_pass_type?
if parent_node.last_argument&.block_pass_type?
correct_block_pass(corrector, parent_node)
else
correct_block(corrector, parent_node)
Expand All @@ -116,7 +116,7 @@ def correct_block(corrector, node)

def correct_block_pass(corrector, node)
if unsorted_dir_glob_pass?(node)
block_arg = node.arguments.last
block_arg = node.last_argument

corrector.remove(last_arg_range(node))
corrector.insert_after(node, ".sort.each(#{block_arg.source})")
Expand All @@ -130,9 +130,7 @@ def correct_block_pass(corrector, node)
# @return [Parser::Source::Range]
#
def last_arg_range(node)
node.arguments.last.source_range.with(
begin_pos: node.arguments[-2].source_range.end_pos
)
node.last_argument.source_range.with(begin_pos: node.arguments[-2].source_range.end_pos)
end

def unsorted_dir_loop?(node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class TrailingCommaInAttributeDeclaration < Base
MSG = 'Avoid leaving a trailing comma in attribute declarations.'

def on_send(node)
return unless node.attribute_accessor? && node.arguments.last.def_type?
return unless node.attribute_accessor? && node.last_argument.def_type?

trailing_comma = trailing_comma_range(node)

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/mixin/check_line_breakable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def process_args(args)

# @api private
def already_on_multiple_lines?(node)
return node.first_line != node.arguments.last.last_line if node.def_type?
return node.first_line != node.last_argument.last_line if node.def_type?

!node.single_line?
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/naming/block_forwarding.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def self.autocorrect_incompatible_with
def on_def(node)
return if node.arguments.empty?

last_argument = node.arguments.last
last_argument = node.last_argument
return if expected_block_forwarding_style?(node, last_argument)

register_offense(last_argument, node)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/naming/memoized_instance_variable_name.rb
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def on_or_asgn(node)

# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def on_defined?(node)
arg = node.arguments.first
arg = node.first_argument
return false unless arg.ivar_type?

method_node, method_name = find_definition(node)
Expand Down
4 changes: 2 additions & 2 deletions lib/rubocop/cop/style/access_modifier_declarations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,12 @@ def message(range)

def find_corresponding_def_node(node)
if access_modifier_with_symbol?(node)
method_name = node.arguments.first.value
method_name = node.first_argument.value
node.parent.each_child_node(:def).find do |child|
child.method?(method_name)
end
else
node.arguments.first
node.first_argument
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/style/accessor_grouping.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def separate_accessors(node)
*processed_source.ast_with_comments[arg].map(&:text),
"#{node.method_name} #{arg.source}"
]
if arg == node.arguments.first
if arg == node.first_argument
lines
else
indent = ' ' * node.loc.column
Expand Down
8 changes: 4 additions & 4 deletions lib/rubocop/cop/style/case_like_if.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def find_target_in_send_node(node)
when :==, :eql?, :equal?
find_target_in_equality_node(node)
when :===
node.arguments.first
node.first_argument
when :include?, :cover?
find_target_in_include_or_cover_node(node)
when :match, :match?, :=~
Expand All @@ -134,7 +134,7 @@ def find_target_in_send_node(node)
end

def find_target_in_equality_node(node)
argument = node.arguments.first
argument = node.first_argument
receiver = node.receiver
return unless argument && receiver

Expand All @@ -152,7 +152,7 @@ def find_target_in_include_or_cover_node(node)
end

def find_target_in_match_node(node)
argument = node.arguments.first
argument = node.first_argument
receiver = node.receiver
return unless receiver

Expand Down Expand Up @@ -185,7 +185,7 @@ def collect_conditions(node, target, conditions)
def condition_from_send_node(node, target)
case node.method_name
when :is_a?
node.arguments.first if node.receiver == target
node.first_argument if node.receiver == target
when :==, :eql?, :equal?
condition_from_equality_node(node, target)
when :=~, :match, :match?
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/style/empty_literal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def first_argument_unparenthesized?(node)
parent = node.parent
return false unless parent && %i[send super zsuper].include?(parent.type)

node.equal?(parent.arguments.first) && !parentheses?(node.parent)
node.equal?(parent.first_argument) && !parentheses?(node.parent)
end

def replacement_range(node)
Expand Down
6 changes: 3 additions & 3 deletions lib/rubocop/cop/style/eval_with_location.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def on_send(node)
# are considered.
return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)

code = node.arguments.first
code = node.first_argument
return unless code && (code.str_type? || code.dstr_type?)

check_location(node, code)
Expand Down Expand Up @@ -165,7 +165,7 @@ def check_file(node, file_node)
end

def check_line(node, code)
line_node = node.arguments.last
line_node = node.last_argument
line_diff = line_difference(line_node, code)
if line_diff.zero?
add_offense_for_same_line(node, line_node)
Expand Down Expand Up @@ -227,7 +227,7 @@ def add_offense_for_missing_location(node, code)
end

def missing_line(node, code)
line_diff = line_difference(node.arguments.last, code)
line_diff = line_difference(node.last_argument, code)
sign = line_diff.positive? ? :+ : :-
expected_line(sign, line_diff)
end
Expand Down
4 changes: 2 additions & 2 deletions lib/rubocop/cop/style/explicit_block_argument.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def on_yield(node)

def extract_block_name(def_node)
if def_node.block_argument?
def_node.arguments.last.name
def_node.last_argument.name
else
'block'
end
Expand Down Expand Up @@ -127,7 +127,7 @@ def call_like?(node)
end

def insert_argument(node, corrector, block_name)
last_arg = node.arguments.last
last_arg = node.last_argument
arg_range = range_with_surrounding_comma(last_arg.source_range, :right)
replacement = " &#{block_name}"
replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/style/method_call_with_args_parentheses.rb
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ def args_end(node)
def args_parenthesized?(node)
return false unless node.arguments.one?

first_node = node.arguments.first
first_node = node.first_argument
first_node.begin_type? && first_node.parenthesized_call?
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/style/method_def_parentheses.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def anonymous_arguments?(node)
return true if node.arguments.any? do |arg|
arg.forward_arg_type? || arg.restarg_type? || arg.kwrestarg_type?
end
return false unless (last_argument = node.arguments.last)
return false unless (last_argument = node.last_argument)

last_argument.blockarg_type? && last_argument.name.nil?
end
Expand Down
4 changes: 2 additions & 2 deletions lib/rubocop/cop/style/redundant_argument.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def on_send(node)
return unless redundant_argument?(node)

offense_range = argument_range(node)
message = format(MSG, arg: node.arguments.first.source)
message = format(MSG, arg: node.first_argument.source)

add_offense(offense_range, message: message) do |corrector|
corrector.remove(offense_range)
Expand All @@ -80,7 +80,7 @@ def redundant_argument?(node)
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
return false if redundant_argument.nil?

node.arguments.first == redundant_argument
node.first_argument == redundant_argument
end

def redundant_arg_for_method(method_name)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/style/redundant_sort.rb
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def suffix(sorter)
end

def arg_node(node)
node.arguments.first
node.first_argument
end

def arg_value(node)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/style/select_by_regexp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def find_regexp(node, block)
return node.child_nodes.first if node.match_with_lvasgn_type?

if node.receiver.lvar_type? &&
(block.numblock_type? || node.receiver.source == block.arguments.first.source)
(block.numblock_type? || node.receiver.source == block.first_argument.source)
node.first_argument
elsif node.first_argument.lvar_type?
node.receiver
Expand Down