Class: YARD::RegistryResolver
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
|
|
Inherits: | Object |
Defined in: | lib/yard/registry_resolver.rb |
Overview
Handles all logic for complex lexical and inherited object resolution. Used by Registry.resolve, so there is no need to use this class directly.
Class Method Summary
-
.new(registry = Registry) ⇒ RegistryResolver
constructor
Creates a new resolver object for a registry.
Instance Method Summary
-
#lookup_by_path(path, opts = {}) ⇒ CodeObjects::Base, ...
Performs a lookup on a given path in the registry.
-
#collect_namespaces(object)
private
Collects and returns all inherited namespaces for a given object.
-
#lookup_path_direct(namespace, path, type)
private
Performs a lexical lookup from a namespace for a path and a type hint.
-
#lookup_path_inherited(namespace, path, type)
private
Performs a lookup through the inheritance chain on a path with a type hint.
- #split_on_separators_match ⇒ Regexp private
- #starts_with_default_separator_match ⇒ Regexp private
- #starts_with_separator_match ⇒ Regexp private
-
#validate(obj, type)
private
return [Boolean] if the obj's type matches the provided type.
CodeObjects::NamespaceMapper
- Included
#clear_separators | Clears the map of separators. |
#default_separator | Gets or sets the default separator value to use when no separator for the namespace can be determined. |
#register_separator | Registers a separator with an optional set of valid types that must follow the separator lexically. |
#separators, #separators_for_type, #separators_match, #types_for_separator, | |
#unregister_separator_by_type | Unregisters a separator by a type. |
Constructor Details
.new(registry = Registry) ⇒ RegistryResolver
Creates a new resolver object for a registry.
# File 'lib/yard/registry_resolver.rb', line 16
def initialize(registry = Registry) @registry = registry @default_sep = nil # Preload all code objects for separator declarations YARD::CodeObjects.constants.map {|t| YARD::CodeObjects.const_get(t) } end
Instance Method Details
#collect_namespaces(object) (private)
Collects and returns all inherited namespaces for a given object
# File 'lib/yard/registry_resolver.rb', line 181
def collect_namespaces(object) return [] unless object.respond_to?(:inheritance_tree) nss = object.inheritance_tree(true) if object.respond_to?(:superclass) nss |= [P('Object')] if object.superclass != P('BasicObject') nss |= [P('BasicObject')] end nss end
#lookup_by_path(path, opts = {}) ⇒ CodeObjects::Base, ...
Performs a lookup on a given path in the registry. Resolution will occur
in a similar way to standard Ruby identifier resolution, doing lexical
lookup, as well as (optionally) through the inheritance chain. A proxy
object can be returned if the lookup fails for future resolution. The
proxy will be type hinted with the type
used in the original lookup.
# File 'lib/yard/registry_resolver.rb', line 50
def lookup_by_path(path, opts = {}) path = path.to_s namespace = opts[:namespace] inheritance = opts[:inheritance] || false proxy_fallback = opts[:proxy_fallback] || false type = opts[:type] if namespace.is_a?(CodeObjects::Proxy) return proxy_fallback ? CodeObjects::Proxy.new(namespace, path, type) : nil end if namespace == :root || !namespace namespace = @registry.root else namespace = namespace.parent until namespace.is_a?(CodeObjects::NamespaceObject) end orignamespace = namespace if path =~ starts_with_default_separator_match path = $' namespace = @registry.root orignamespace = @registry.root end resolved = nil lexical_lookup = 0 while namespace && !resolved resolved = lookup_path_direct(namespace, path, type) resolved ||= lookup_path_inherited(namespace, path, type) if inheritance break if resolved namespace = namespace.parent lexical_lookup += 1 end # method objects cannot be resolved through lexical lookup by more than 1 ns if lexical_lookup > 1 && resolved.is_a?(CodeObjects::MethodObject) resolved = nil end if proxy_fallback resolved ||= CodeObjects::Proxy.new(orignamespace, path, type) end resolved end
#lookup_path_direct(namespace, path, type) (private)
Performs a lexical lookup from a namespace for a path and a type hint.
# File 'lib/yard/registry_resolver.rb', line 104
def lookup_path_direct(namespace, path, type) result = namespace.root? && validate(@registry.at(path), type) return result if result if path =~ starts_with_separator_match return validate(@registry.at(namespace.path + path), type) end separators.each do |sep| result = validate(@registry.at("#{namespace.path}#{sep}#{path}"), type) return result if result end nil end
#lookup_path_inherited(namespace, path, type) (private)
Performs a lookup through the inheritance chain on a path with a type hint.
# File 'lib/yard/registry_resolver.rb', line 121
def lookup_path_inherited(namespace, path, type) resolved = nil last_obj = namespace scopes = [] last_sep = nil pos = 0 if path =~ starts_with_separator_match last_sep = $1 path = $' end path.scan(split_on_separators_match).each do |part, sep| cur_obj = nil pos += part.length pos += sep.length parsed_end = pos == path.length if !last_obj || (!parsed_end && !last_obj.is_a?(CodeObjects::NamespaceObject)) break # can't continue end collect_namespaces(last_obj).each do |ns| next if ns.is_a?(CodeObjects::Proxy) found = nil search_seps = [] scopes.each do |scope| search_seps += separators_for_type(scope) end if search_seps.empty? search_seps = if ns.type == :root [""] elsif last_sep.nil? separators else [@default_sep] end end ([last_sep] | search_seps).compact.each do |search_sep| found = @registry.at(ns.path + search_sep.to_s + part) break if found end break cur_obj = found if found end last_sep = sep scopes = types_for_separator(sep) || [] last_obj = cur_obj resolved = cur_obj if parsed_end && cur_obj && (type.nil? || type == cur_obj.type) end resolved end
#split_on_separators_match ⇒ Regexp
(private)
# File 'lib/yard/registry_resolver.rb', line 206
def split_on_separators_match @@split_on_separators_match ||= /(.+?)(#{separators_match}|$)/ end
#starts_with_default_separator_match ⇒ Regexp
(private)
# File 'lib/yard/registry_resolver.rb', line 194
def starts_with_default_separator_match @@starts_with_default_separator_match ||= /\A#{default_separator}/ end
#starts_with_separator_match ⇒ Regexp
(private)
# File 'lib/yard/registry_resolver.rb', line 200
def starts_with_separator_match @@starts_with_separator_match ||= /\A(#{separators_match})/ end
#validate(obj, type) (private)
return [Boolean] if the obj's type matches the provided type.
# File 'lib/yard/registry_resolver.rb', line 99
def validate(obj, type) !type || (obj && obj.type == type) ? obj : nil end