def inspect_constants(source = constant, ignore = [])
      names          = []
      source_name    = source.name
      have_children  = []
      include_source = source != Object

      if include_source and !ignore.include?(source_name)
        names  << source_name
        ignore << source_name
      end

      source.constants.each do |name|
        next if skip_constant?(source, name)

        full_name = include_source ? "#{source_name}::#{name}" : name.to_s

        # In certain cases this code tries to load a constant that apparently
        # *is* defined but craps out upon error (e.g. Bundler::Specification).
        begin
          constant = source.const_get(name)
        rescue Exception => error
          warn error.message
          next
        end

        # Skip those that we've already processed.
        if ignore.include?(full_name) or source == constant
          next
        end

        names         << full_name
        ignore        << full_name
        have_children << constant if process_child_constants?(constant)
      end

      have_children.each do |const|
        names |= inspect_constants(const, ignore)
      end

      # Reject every constant that, if we should include the source name, was
      # not defined under that constant. This applies on for example Rubinius
      # since `Range::Enumerator` is a constant that points to
      # `Enumerable::Enumerator`.
      if include_source
        names = names.select { |name| name.start_with?(source_name) }
      end

      return names
    end
def inspect_constants(source = constant, ignore = [])
      names          = []
      source_name    = source.name
      have_children  = []
      include_source = source != Object

      if include_source and !ignore.include?(source_name)
        names  << source_name
        ignore << source_name
      end

      source.constants.each do |name|
        next if skip_constant?(source, name)

        full_name = include_source ? "#{source_name}::#{name}" : name.to_s

        # In certain cases this code tries to load a constant that apparently
        # *is* defined but craps out upon error (e.g. Bundler::Specification).
        begin
          constant = source.const_get(name)
        rescue Exception => error
          warn error.message
          next
        end

        # Skip those that we've already processed.
        if ignore.include?(full_name) or source == constant
          next
        end

        names         << full_name
        ignore        << full_name
        have_children << constant if process_child_constants?(constant)
      end

      have_children.each do |const|
        names |= inspect_constants(const, ignore)
      end

      # Reject every constant that, if we should include the source name, was
      # not defined under that constant. This applies on for example Rubinius
      # since `Range::Enumerator` is a constant that points to
      # `Enumerable::Enumerator`.
      if include_source
        names = names.select { |name| name.start_with?(source_name) }
      end

      return names
    end
@param [String|Class] constant


 Returns an Array containing all constants and their child constants
 (recursively).

 @param [Class] source
 @param [Array] ignore
 @return [Array<String>]