class Solargraph::Source::Chain
A chain of constants, variables, and method calls for inferring types of values.
Constants
- UNDEFINED_CALL
- UNDEFINED_CONSTANT
Attributes
links[R]
@return [Array<Source::Chain::Link>]
node[R]
Public Class Methods
new(links, node = nil, splat = false)
click to toggle source
@param links [Array<Chain::Link>]
# File lib/solargraph/source/chain.rb, line 38 def initialize links, node = nil, splat = false @links = links.clone @links.push UNDEFINED_CALL if @links.empty? head = true @links.map! do |link| result = (head ? link.clone_head : link.clone_body) head = false result end @node = node @splat = splat end
Public Instance Methods
base()
click to toggle source
@return [Chain]
# File lib/solargraph/source/chain.rb, line 52 def base @base ||= Chain.new(links[0..-2]) end
constant?()
click to toggle source
@return [Boolean]
# File lib/solargraph/source/chain.rb, line 96 def constant? links.last.is_a?(Chain::Constant) end
define(api_map, name_pin, locals)
click to toggle source
@param api_map [ApiMap] @param name_pin [Pin::Base] @param locals [Array<Pin::Base>] @return [Array<Pin::Base>]
# File lib/solargraph/source/chain.rb, line 60 def define api_map, name_pin, locals return [] if undefined? working_pin = name_pin links[0..-2].each do |link| pins = link.resolve(api_map, working_pin, locals) type = infer_first_defined(pins, working_pin, api_map) return [] if type.undefined? working_pin = Pin::ProxyType.anonymous(type) end links.last.last_context = working_pin links.last.resolve(api_map, working_pin, locals) end
defined?()
click to toggle source
# File lib/solargraph/source/chain.rb, line 91 def defined? !undefined? end
infer(api_map, name_pin, locals)
click to toggle source
@param api_map [ApiMap] @param name_pin [Pin::Base] @param locals [Array<Pin::Base>] @return [ComplexType]
# File lib/solargraph/source/chain.rb, line 77 def infer api_map, name_pin, locals pins = define(api_map, name_pin, locals) infer_first_defined(pins, links.last.last_context, api_map) end
literal?()
click to toggle source
@return [Boolean]
# File lib/solargraph/source/chain.rb, line 83 def literal? links.last.is_a?(Chain::Literal) end
splat?()
click to toggle source
# File lib/solargraph/source/chain.rb, line 100 def splat? @splat end
undefined?()
click to toggle source
# File lib/solargraph/source/chain.rb, line 87 def undefined? links.any?(&:undefined?) end
Private Instance Methods
infer_first_defined(pins, context, api_map)
click to toggle source
@param pins [Array<Pin::Base>] @param api_map [ApiMap] @return [ComplexType]
# File lib/solargraph/source/chain.rb, line 109 def infer_first_defined pins, context, api_map possibles = [] pins.each do |pin| # Avoid infinite recursion next if @@inference_stack.include?(pin.identity) @@inference_stack.push pin.identity type = pin.typify(api_map) @@inference_stack.pop if type.defined? possibles.push type break if pin.is_a?(Pin::Method) end end if possibles.empty? # Limit method inference recursion return ComplexType::UNDEFINED if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method) @@inference_depth += 1 pins.each do |pin| # Avoid infinite recursion next if @@inference_stack.include?(pin.identity) @@inference_stack.push pin.identity type = pin.probe(api_map) @@inference_stack.pop if type.defined? possibles.push type break if pin.is_a?(Pin::Method) end end @@inference_depth -= 1 end return ComplexType::UNDEFINED if possibles.empty? type = if possibles.length > 1 sorted = possibles.map { |t| t.rooted? ? "::#{t}" : t.to_s }.sort { |a, _| a == 'nil' ? 1 : 0 } ComplexType.parse(*sorted) else possibles.first end return type if context.nil? || context.return_type.undefined? type.self_to(context.return_type.namespace) end