module CoreDocs::MethodInfo

Public Class Methods

aliases(meth) click to toggle source

Retrives aliases of a method @param [Method, UnboundMethod] meth The method object. @return [Array] The aliases of a method if it exists

otherwise, return empty array
# File lib/core_docs.rb, line 48
def self.aliases(meth)
  # host        = is_singleton?(meth) ? meth.receiver : meth.owner
  # method_type = is_singleton?(meth) ? :method : :instance_method

  # methods = Pry::Method.send(:all_from_common, host, method_type, false).
  #                       map { |m| m.instance_variable_get(:@method) }

  # methods.select { |m| host.send(method_type,m.name) == host.send(method_type,meth.name) }.
  #         reject { |m| m.name == meth.name }.
  #         map    { |m| host.send(method_type,m.name) }
  []
end
c_files_found?(gem_dir) click to toggle source

@param [String] root directory path of gem that method belongs to @return [Boolean] true if c files exist?

# File lib/core_docs.rb, line 123
def self.c_files_found?(gem_dir)
  Dir.glob("#{gem_dir}/**/*.c").count > 0
end
cache(meth) click to toggle source

Cache the file that holds the method or return immediately if file is already cached. Return if the method cannot be cached - i.e is a C stdlib method. @param [Method, UnboundMethod] meth The method object.

# File lib/core_docs.rb, line 211
def self.cache(meth)
  file, _ = meth.source_location

  return if is_eval_method?(meth)
  return if cached?(meth)

  if !file
    parse_and_cache_if_gem_cext(meth)
    return
  end

  log.enter_level(Logger::FATAL) do
    YARD.parse(file)
  end
end
cached?(meth) click to toggle source

Check whether the file containing the method is already cached. @param [Method, UnboundMethod] meth The method object. @return [Boolean] Whether the method is cached.

# File lib/core_docs.rb, line 71
def self.cached?(meth)
  !!registry_lookup(meth)
end
find_gem_dir(meth) click to toggle source

@param [Method, UnboundMethod] meth The method object. @return [String] root directory path of gem that method belongs to,

nil if could not be found
# File lib/core_docs.rb, line 143
def self.find_gem_dir(meth)
  # host = method_host(meth)

  # begin
  #   host_source_location, _ =  WrappedModule.new(host).source_location
  #   break if host_source_location != nil
  #   return unless host.name
  #   host = eval(host.namespace_name)
  # end while host

  # # we want to exclude all source_locations that aren't gems (i.e
  # # stdlib)
  # if host_source_location && host_source_location =~ %r{/gems/}
  #   gem_root(host_source_location)
  # else

    # the WrappedModule approach failed, so try our backup approach
    gem_dir_from_method(meth)
  # end
end
gem_dir_from_method(meth) click to toggle source

Try to recover the gem directory of a gem based on a method object. @param [Method, UnboundMethod] meth The method object. @return [String, nil] The located gem directory.

# File lib/core_docs.rb, line 189
def self.gem_dir_from_method(meth)
  guess = 0

  host = method_host(meth)
  return unless host.name
  root_module_name = host.name.split("::").first
  while gem_name = guess_gem_name_from_module_name(root_module_name, guess)
    matches = $LOAD_PATH.grep %r{/gems/#{gem_name}} if !gem_name.empty?
    if matches && matches.any?
      return gem_root(matches.first)
    else
      guess += 1
    end
  end

  nil
end
gem_root(dir) click to toggle source

FIXME: this is unnecessarily limited to ext/ and lib/ folders @return [String] The root folder of a given gem directory.

# File lib/core_docs.rb, line 134
def self.gem_root(dir)
  if index = dir.rindex(/\/(?:lib|ext)(?:\/|$)/)
    dir[0..index-1]
  end
end
guess_gem_name_from_module_name(name, guess) click to toggle source

Try to guess what the gem name will be based on the name of the module. We try a few approaches here depending on the `guess` parameter. @param [String] name The name of the module. @param [Fixnum] guess The current guessing approach to use. @return [String, nil] The guessed gem name, or `nil` if out of guesses.

# File lib/core_docs.rb, line 169
def self.guess_gem_name_from_module_name(name, guess)
  case guess
  when 0
    name.downcase
  when 1
    name.scan(/[A-Z][a-z]+/).map(&:downcase).join('_')
  when 2
    name.scan(/[A-Z][a-z]+/).map(&:downcase).join('_').sub("_", "-")
  when 3
    name.scan(/[A-Z][a-z]+/).map(&:downcase).join('-')
  when 4
    name
  else
    nil
  end
end
info_for(meth) click to toggle source

Retrieve the YARD object that contains the method data. @param [Method, UnboundMethod] meth The method object. @return [YARD::CodeObjects::MethodObject] The YARD data for the method.

# File lib/core_docs.rb, line 92
def self.info_for(meth)
  cache(meth)
  registry_lookup(meth)
end
is_eval_method?(meth) click to toggle source

Determine whether a method is an eval method. @return [Boolean] Whether the method is an eval method.

# File lib/core_docs.rb, line 99
def self.is_eval_method?(meth)
  file, _ = meth.source_location
  if file =~ /(\(.*\))|<.*>/
    true
  else
    false
  end
end
is_singleton?(meth) click to toggle source

Checks whether method is a singleton (i.e class method) @param [Method, UnboundMethod] meth @param [Boolean] true if singleton

# File lib/core_docs.rb, line 64
def self.is_singleton?(meth)
  receiver_notation_for(meth).include?('.')
end
method_host(meth) click to toggle source

@return [Object] The host of the method (receiver or owner).

# File lib/core_docs.rb, line 128
def self.method_host(meth)
  is_singleton?(meth) && Module === meth.receiver ? meth.receiver : meth.owner
end
parse_and_cache_if_gem_cext(meth) click to toggle source

Attempts to find the c source files if method belongs to a gem and use YARD to parse and cache the source files for display

@param [Method, UnboundMethod] meth The method object.

# File lib/core_docs.rb, line 112
def self.parse_and_cache_if_gem_cext(meth)
  if gem_dir = find_gem_dir(meth)
    if c_files_found?(gem_dir)
      warn "Scanning and caching *.c files..."
      YARD.parse("#{gem_dir}/**/*.c")
    end
  end
end
receiver_notation_for(meth) click to toggle source

Convert a method object into the `Class#method` string notation. @param [Method, UnboundMethod] meth @return [String] The method in string receiver notation. @note This mess is needed in order to support all the modern Rubies. YOU

must figure out a better way to distinguish between class methods and
instance methods.
# File lib/core_docs.rb, line 36
def self.receiver_notation_for(meth)
  match = meth.inspect.match(/\A#<(?:Unbound)?Method: (.+)([#\.].+)>\z/)
  owner = meth.owner.to_s.sub(/#<.+?:(.+?)>/, '\1')
  name = match[2]
  name.sub!('#', '.') if match[1] =~ /\A#<Class:/
  owner + name
end
registry_lookup(meth) click to toggle source
# File lib/core_docs.rb, line 75
def self.registry_lookup(meth)
  obj = YARD::Registry.at(receiver_notation_for(meth))
  if obj.nil?
    if !(aliases = aliases(meth)).empty?
      obj = YARD::Registry.at(receiver_notation_for(aliases.first))
    elsif meth.owner == Kernel
      # YARD thinks that some methods are on Object when
      # they're actually on Kernel; so try again on Object if Kernel fails.
      obj = YARD::Registry.at("Object##{meth.name}")
    end
  end
  obj
end