class RuboCop::Cop::Sorbet::VoidCheckedTests

sig { void.checked(:never) }
sig { returns(T.anything).checked(:tests) }
sig { void }
# good
sig { void.checked(:tests) }
# bad
@example
earlier. Versions released after 2023-04-14 include ‘T.anything`.)
which does not have `T.anything` (meaning versions 0.5.10781 or
- Use `.void.checked(:never)` if you are on an older version of Sorbet
checking for the rest of the parameters.
- Use `.returns(T.anything).checked(:tests)` to keep the runtime type
falsy depending on the method’s implementation.
will be the truthy ‘VOID` value, while the non-test return value may be
result of a `.void` method, because the returned value in test code
environments. This is particularly troublesome if branching on the
will return different values in tests compared with non-test
runtime type checking is enabled for the method. Methods marked `.void`
Using `.void` changes the value returned from the method, but only if
Disallows the usage of `.void.checked(:tests)`.

def on_signature(node)

def on_signature(node)
  checked_send = checked_tests(node).first
  return unless checked_send
  if (parent = node.parent) && (sibling_index = node.sibling_index)
    later_siblings = parent.children[(sibling_index + 1)..]
    if (def_node = later_siblings.find { |sibling| sibling.is_a?(RuboCop::AST::DefNode) })
      # Sorbet requires that `initialize` methods return `.void`
      # (A stylistic convention which happens to be enforced by Sorbet)
      return if def_node.method?(:initialize)
    end
  end
  void_send = top_level_void(node.body)
  return unless void_send
  add_offense(
    void_send.selector,
    message: MESSAGE,
  ) do |corrector|
    corrector.replace(void_send.selector, "returns(T.anything)")
  end
end

def top_level_void(node)

def top_level_void(node)
 unless node.is_a?(RuboCop::AST::SendNode)
e.method?(:void)

(recv = node.receiver)
level_void(recv)