# Class: YARD::CodeObjects::Proxy

Inherits:
  Object
  - Object
  - YARD::CodeObjects::Proxy
  show all

Defined in:
  lib/yard/code_objects/proxy.rb

## Overview

The Proxy class is a way to lazily resolve code objects in cases where the object may not yet exist. A proxy simply stores an unresolved path until a method is called on the object, at which point it does a lookup using Registry.resolve. If the object is not found, a warning is raised and ProxyMethodError might be raised.

#### Examples:

#####

Creates a Proxy to the String class from a module

    # When the String class is parsed this method will
    # begin to act like the String ClassObject.
    Proxy.new(mymoduleobj, "String")

See Also:

- Registry.resolve
- ProxyMethodError

## Instance Attribute Summary collapse

- #namespace ⇒ Object (also: #parent) readonly

  Returns the value of attribute namespace.

## Class Method Summary collapse

- .===(other) ⇒ Object

## Instance Method Summary collapse

- #<=>(other) ⇒ Boolean
- #===(other) ⇒ Boolean
- #class ⇒ Class

  Returns the class name of the object the proxy is mimicking, if resolved.

- #equal?(other) ⇒ Boolean (also: #==)
- #hash ⇒ Integer

  The object’s hash value (for equality checking).

- #initialize(namespace, name, type = nil) ⇒ Proxy constructor

  Creates a new Proxy.

- #inspect ⇒ String

  Returns a text representation of the Proxy.

- #instance_of?(klass) ⇒ Boolean
- #is_a?(klass) ⇒ Boolean
- #kind_of?(klass) ⇒ Boolean
- #method_missing(meth, *args, &block) ⇒ Object

  Dispatches the method to the resolved object.

- #name(prefix = false) ⇒ Symbol, String

  The name of the object.

- #path ⇒ String (also: #to_s, #to_str, #title)

  If the proxy resolves to an object, returns its path, otherwise guesses at the correct path using the original namespace and name.

- #respond_to?(meth, include_private = false) ⇒ Boolean
- #root? ⇒ Boolean

  This class is never a root object.

- #type ⇒ Symbol

  Returns the type of the proxy.

- #type=(type) ⇒ void

  Allows a parser to infer the type of the proxy by its path.

## Constructor Details

### #initialize(namespace, name, type = nil) ⇒ `Proxy`

Creates a new Proxy

Raises:

- (`ArgumentError`) —

  if namespace is not a NamespaceObject

    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82

    # File 'lib/yard/code_objects/proxy.rb', line 34

    def initialize(namespace, name, type = nil)
      namespace = Registry.root if !namespace || namespace == :root

      if name =~ /^#{NSEPQ}/
        namespace = Registry.root
        name = name[2..-1]
      end

      if name =~ PROXY_MATCH
        @orignamespace = namespace
        @origname = name
        @imethod = true if name.include? ISEP
        namespace = Proxy.new(namespace, $`) unless $`.empty?
        name = $1
      else
        @orignamespace = nil
        @origname = nil
        @imethod = nil
      end

      @name = name.to_sym
      @namespace = namespace
      @obj = nil
      @imethod ||= nil
      self.type = type

      if @namespace.is_a?(ConstantObject)
        unless @namespace.value =~ /\A#{NAMESPACEMATCH}\Z/
          raise Parser::UndocumentableError, "constant mapping for " +
            "#{@origname} (type=#{type.inspect})"
        end

        @origname = nil # forget these for a constant
        @orignamespace = nil
        @namespace = Proxy.new(@namespace.namespace, @namespace.value)
      end

      unless @namespace.is_a?(NamespaceObject) || @namespace.is_a?(Proxy)
        raise ArgumentError, "Invalid namespace object: #{namespace}"
      end

      # If the name begins with "::" (like "::String")
      # this is definitely a root level object, so
      # remove the namespace and attach it to the root
      if @name =~ /^#{NSEPQ}/
        @name.gsub!(/^#{NSEPQ}/, '')
        @namespace = Registry.root
      end
    end

## Dynamic Method Handling

This class handles dynamic methods through the `method_missing` method

### #method_missing(meth, *args, &block) ⇒ `Object`

Dispatches the method to the resolved object.

Raises:

- (`ProxyMethodError`) —

  if the proxy cannot find the real object

    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197

    # File 'lib/yard/code_objects/proxy.rb', line 178

    def method_missing(meth, *args, &block)
      if to_obj
        to_obj.__send__(meth, *args, &block)
      else
        log.warn "Load Order / Name Resolution Problem on #{path}:\n" \
                 "-\n" \
                 "Something is trying to call #{meth} on object #{path} before it has been recognized.\n" \
                 "This error usually means that you need to modify the order in which you parse files\n" \
                 "so that #{path} is parsed before methods or other objects attempt to access it.\n" \
                 "-\n" \
                 "YARD will recover from this error and continue to parse but you *may* have problems\n" \
                 "with your generated documentation. You should probably fix this.\n" \
                 "-\n"
        begin
          super
        rescue NoMethodError
          raise ProxyMethodError, "Proxy cannot call method ##{meth} on object '#{path}'"
        end
      end
    end

## Instance Attribute Details

### #namespace ⇒ `Object` (readonly) Also known as: parent

Returns the value of attribute namespace.

    27
    28
    29

    # File 'lib/yard/code_objects/proxy.rb', line 27

    def namespace
      @namespace
    end

## Class Method Details

### .===(other) ⇒ `Object`

    25

    # File 'lib/yard/code_objects/proxy.rb', line 25

    def self.===(other) other.is_a?(self) end

## Instance Method Details

### #<=>(other) ⇒ `Boolean`

Returns:

- (`Boolean`)

    118
    119
    120
    121
    122
    123
    124

    # File 'lib/yard/code_objects/proxy.rb', line 118

    def <=>(other)
      if other.respond_to? :path
        path <=> other.path
      else
        false
      end
    end

### #===(other) ⇒ `Boolean`

Returns:

- (`Boolean`)

    113
    114
    115

    # File 'lib/yard/code_objects/proxy.rb', line 113

    def ===(other)
      to_obj ? to_obj === other : self.class <= other.class
    end

### #class ⇒ `Class`

Returns the class name of the object the proxy is mimicking, if resolved. Otherwise returns `Proxy`.

Returns:

- (`Class`) —

  the resolved object’s class or `Proxy`

    142
    143
    144

    # File 'lib/yard/code_objects/proxy.rb', line 142

    def class
      to_obj ? to_obj.class : Proxy
    end

### #equal?(other) ⇒ `Boolean` Also known as: ==

Returns:

- (`Boolean`)

    127
    128
    129
    130
    131
    132
    133

    # File 'lib/yard/code_objects/proxy.rb', line 127

    def equal?(other)
      if other.respond_to? :path
        path == other.path
      else
        false
      end
    end

### #hash ⇒ `Integer`

Returns the object’s hash value (for equality checking).

Returns:

- (`Integer`) —

  the object’s hash value (for equality checking)

    137

    # File 'lib/yard/code_objects/proxy.rb', line 137

    def hash; path.hash end

### #inspect ⇒ `String`

Returns a text representation of the Proxy

Returns:

- (`String`) —

  the object’s #inspect method or P(OBJECTPATH)

    91
    92
    93

    # File 'lib/yard/code_objects/proxy.rb', line 91

    def inspect
      to_obj ? to_obj.inspect : "P(#{path})"
    end

### #instance_of?(klass) ⇒ `Boolean`

Returns:

- (`Boolean`)

    161
    162
    163

    # File 'lib/yard/code_objects/proxy.rb', line 161

    def instance_of?(klass)
      self.class == klass
    end

### #is_a?(klass) ⇒ `Boolean`

Returns:

- (`Boolean`)

    108
    109
    110

    # File 'lib/yard/code_objects/proxy.rb', line 108

    def is_a?(klass)
      to_obj ? to_obj.is_a?(klass) : self.class <= klass
    end

### #kind_of?(klass) ⇒ `Boolean`

Returns:

- (`Boolean`)

    166
    167
    168

    # File 'lib/yard/code_objects/proxy.rb', line 166

    def kind_of?(klass)
      self.class <= klass
    end

### #name(prefix = false) ⇒ `Symbol`, `String`

The name of the object

Parameters:

- prefix (`Boolean`) (defaults to: `false`) —

  whether to show a prefix. Implement this in a subclass to define how the prefix is showed.

Returns:

- (`Symbol`) —

  if prefix is false, the symbolized name

- (`String`) —

  if prefix is true, prefix + the name as a String. This must be implemented by the subclass.

    85
    86
    87

    # File 'lib/yard/code_objects/proxy.rb', line 85

    def name(prefix = false)
      prefix ? "#{@imethod && ISEP}#{@name}" : @name
    end

### #path ⇒ `String` Also known as: to_s, to_str, title

If the proxy resolves to an object, returns its path, otherwise guesses at the correct path using the original namespace and name.

Returns:

- (`String`) —

  the assumed path of the proxy (or the real path of the resolved object)

    100
    101
    102

    # File 'lib/yard/code_objects/proxy.rb', line 100

    def path
      to_obj ? to_obj.path : proxy_path
    end

### #respond_to?(meth, include_private = false) ⇒ `Boolean`

Returns:

- (`Boolean`)

    171
    172
    173

    # File 'lib/yard/code_objects/proxy.rb', line 171

    def respond_to?(meth, include_private = false)
      to_obj ? to_obj.respond_to?(meth, include_private) : super
    end

### #root? ⇒ `Boolean`

This class is never a root object

Returns:

- (`Boolean`)

    200

    # File 'lib/yard/code_objects/proxy.rb', line 200

    def root?; false end

### #type ⇒ `Symbol`

Returns the type of the proxy. If it cannot be resolved at the time of the call, it will either return the inferred proxy type (see #type=) or `:proxy`

Returns:

- (`Symbol`) —

  the Proxy’s type

See Also:

- #type=

    151
    152
    153

    # File 'lib/yard/code_objects/proxy.rb', line 151

    def type
      to_obj ? to_obj.type : @type || :proxy
    end

### #type=(type) ⇒ `void`

This method returns an undefined value.

Allows a parser to infer the type of the proxy by its path.

Parameters:

- type (`#to_sym`) —

  the proxy’s inferred type

    158

    # File 'lib/yard/code_objects/proxy.rb', line 158

    def type=(type) @type = type ? type.to_sym : nil end