class RuboCop::Cop::Sorbet::BindingConstantWithoutTypeAlias

FooOrBar = T.type_alias { T.any(Foo, Bar) }
# good
FooOrBar = T.any(Foo, Bar)
# bad
@example
to a constant directly. To bind the value, one must use ‘T.type_alias`.
Disallows binding the return value of `T.any`, `T.all`, `T.enum`

def on_casgn(node)

def on_casgn(node)
  expression = node.expression
  return if expression.nil? # multiple assignment
  type_alias_without_block(expression) do |type|
    return add_offense(expression, message: WITHOUT_BLOCK_MSG) do |corrector|
      corrector.replace(expression, "T.type_alias { #{type.source} }")
    end
  end
  return if type_alias_with_block?(expression)
  requires_type_alias?(send_leaf(expression)) do
    return add_offense(expression) do |corrector|
      corrector.replace(expression, "T.type_alias { #{expression.source} }")
    end
  end
end

def send_leaf(node)


^^^^^^^^^^^^^^^^^^^^^^^
(send (send (send (send (send (send nil :a) :b) :c) :d) :e) :f)

i.e. in AST

^^^
a.b.c.d.e.f

i.e. in Ruby

Given nested send nodes, returns the leaf with explicit receiver.
def send_leaf(node)
  node = node.receiver while node&.receiver&.send_type?
  node
end