def each_descendant(*types, &block)
      return to_enum(__method__, *types) unless block_given?

      types.flatten!

      if types.empty?
        visit_descendants(&block)
      else
        visit_descendants_with_types(types, &block)
      end

      self
    end
def each_descendant(*types, &block)
      return to_enum(__method__, *types) unless block_given?

      types.flatten!

      if types.empty?
        visit_descendants(&block)
      else
        visit_descendants_with_types(types, &block)
      end

      self
    end
Calls the given block for each descendant node with depth first order.
 If no block is given, an `Enumerator` is returned.

 @overload each_descendant
   Yield all nodes.
 @overload each_descendant(type)
   Yield only nodes matching the type.
   @param [Symbol] type a node type
 @overload each_descendant(type_a, type_b, ...)
   Yield only nodes matching any of the types.
   @param [Symbol] type_a a node type
   @param [Symbol] type_b a node type
 @overload each_descendant(types)
   Yield only nodes matching any of types in the array.
   @param [Array<Symbol>] types an array containing node types
 @yieldparam [Node] node each descendant node
 @return [self] if a block is given
 @return [Enumerator] if no block is given