class RuboCop::Cop::Lint::AmbiguousOperator
do_something(*some_array)
# With parentheses, there’s no ambiguity.
# good
@example
do_something *some_array
# a ‘*` method invocation (i.e. `do_something.*(some_array)`).
# The `*` is interpreted as a splat operator but it could possibly be
# bad
@example
method invocation without parentheses.
This cop checks for ambiguous operators in the first argument of a
def find_offense_node_by(diagnostic)
def find_offense_node_by(diagnostic) ast = processed_source.ast ast.each_node(:splat, :block_pass, :kwsplat) do |node| next unless offense_position?(node, diagnostic) offense_node = offense_node(node) return offense_node if offense_node end ast.each_node(:send).find do |send_node| first_argument = send_node.first_argument first_argument && offense_position?(first_argument, diagnostic) && unary_operator?(first_argument, diagnostic) end end
def message(diagnostic)
def message(diagnostic) operator = diagnostic.location.source hash = AMBIGUITIES[operator] format(MSG_FORMAT, hash) end
def offense_node(node)
def offense_node(node) case node.type when :splat, :block_pass node.parent when :kwsplat node.parent.parent end end
def offense_position?(node, diagnostic)
def offense_position?(node, diagnostic) node.source_range.begin_pos == diagnostic.location.begin_pos end
def on_new_investigation
def on_new_investigation processed_source.diagnostics.each do |diagnostic| next unless diagnostic.reason == :ambiguous_prefix offense_node = find_offense_node_by(diagnostic) next unless offense_node message = message(diagnostic) add_offense( diagnostic.location, message: message, severity: diagnostic.level ) do |corrector| add_parentheses(offense_node, corrector) end end end
def unary_operator?(node, diagnostic)
def unary_operator?(node, diagnostic) node.source.start_with?(diagnostic.arguments[:prefix]) end