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