class Solargraph::Pin::DelegatedMethod

allows aliasing a method from a different closure (class/module etc).
A DelegatedMethod is a more complicated version of a MethodAlias that

def initialize(method: nil, receiver: nil, name: method&.name, receiver_method_name: name, **splat)

Parameters:
  • receiver_method_name (String) -- the method name that will be called on the receiver (defaults to :name).
  • name (String) --
  • receiver (Source::Chain, nil) -- the source code used to resolve the receiver for this delegated method.
  • method (Method, nil) -- an already resolved method pin.
def initialize(method: nil, receiver: nil, name: method&.name, receiver_method_name: name, **splat)
  raise ArgumentError, 'either :method or :receiver is required' if (method && receiver) || (!method && !receiver)
  super(name: name, **splat)
  @receiver_chain = receiver
  @resolved_method = method
  @receiver_method_name = receiver_method_name
end

def print_chain(chain)

Returns:
  • (String) -

Parameters:
  • chain (Source::Chain) --
def print_chain(chain)
  out = +''
  chain.links.each_with_index do |link, index|
    if index > 0
      if Source::Chain::Constant
        out << '::' unless link.word.start_with?('::')
      else
        out << '.'
      end
    end
    out << link.word
  end
  out
end

def resolvable?(api_map)

Parameters:
  • api_map (ApiMap) --
def resolvable?(api_map)
  resolve_method(api_map)
  !!@resolved_method
end

def resolve_method api_map

Returns:
  • (Pin::Method, nil) -

Parameters:
  • api_map (ApiMap) --
def resolve_method api_map
  return if @resolved_method
  resolver = @receiver_chain.define(api_map, self, []).first
  unless resolver
    Solargraph.logger.warn \
      "Delegated receiver for #{path} was resolved to nil from `#{print_chain(@receiver_chain)}'"
    return
  end
  receiver_type = resolver.return_type
  return if receiver_type.undefined?
  receiver_path, method_scope =
    if @receiver_chain.constant?
      # HACK: the `return_type` of a constant is Class<Whatever>, but looking up a method expects

      # the arguments `"Whatever"` and `scope: :class`.

      [receiver_type.to_s.sub(/^Class<(.+)>$/, '\1'), :class]
    else
      [receiver_type.to_s, :instance]
    end
  method_stack = api_map.get_method_stack(receiver_path, @receiver_method_name, scope: method_scope)
  @resolved_method = method_stack.first
end