Class: Solargraph::Source::Chain

Inherits:
Object
  • Object
show all
Includes:
Equality, Logging
Defined in:
lib/solargraph/source/chain.rb,
lib/solargraph/source/chain/if.rb,
lib/solargraph/source/chain/or.rb,
lib/solargraph/source/chain/call.rb,
lib/solargraph/source/chain/hash.rb,
lib/solargraph/source/chain/head.rb,
lib/solargraph/source/chain/link.rb,
lib/solargraph/source/chain/array.rb,
lib/solargraph/source/chain/q_call.rb,
lib/solargraph/source/chain/literal.rb,
lib/solargraph/source/chain/z_super.rb,
lib/solargraph/source/chain/constant.rb,
lib/solargraph/source/chain/variable.rb,
lib/solargraph/source/chain/block_symbol.rb,
lib/solargraph/source/chain/block_variable.rb,
lib/solargraph/source/chain/class_variable.rb,
lib/solargraph/source/chain/global_variable.rb,
lib/solargraph/source/chain/instance_variable.rb

Overview

Represents an expression as a single call chain at the parse tree level, made up of constants, variables, and method calls, each represented as a Link object.

Computes Pins and/or ComplexTypes representing the interpreted expression.

Defined Under Namespace

Classes: Array, BlockSymbol, BlockVariable, Call, ClassVariable, Constant, GlobalVariable, Hash, Head, If, InstanceVariable, Link, Literal, Or, QCall, Variable, ZSuper

Constant Summary collapse

UNDEFINED_CALL =
Chain::Call.new('<undefined>')
UNDEFINED_CONSTANT =
Chain::Constant.new('<undefined>')
@@inference_stack =
[]
@@inference_depth =
0
@@inference_invalidation_key =
nil
@@inference_cache =
{}

Constants included from Logging

Logging::DEFAULT_LOG_LEVEL, Logging::LOG_LEVELS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging

logger

Methods included from Equality

#==, #eql?, #freeze, #hash

Constructor Details

#initialize(links, node = nil, splat = false) ⇒ Chain

Returns a new instance of Chain.

Parameters:

  • node (Parser::AST::Node, nil) (defaults to: nil)
  • links (::Array<Chain::Link>)
  • splat (Boolean) (defaults to: false)


58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/solargraph/source/chain.rb', line 58

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

Instance Attribute Details

Returns:



46
47
48
# File 'lib/solargraph/source/chain.rb', line 46

def links
  @links
end

#nodeObject (readonly)

Returns the value of attribute node.



48
49
50
# File 'lib/solargraph/source/chain.rb', line 48

def node
  @node
end

Instance Method Details

#baseChain

Returns:



72
73
74
# File 'lib/solargraph/source/chain.rb', line 72

def base
  @base ||= Chain.new(links[0..-2])
end

#constant?Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/solargraph/source/chain.rb', line 155

def constant?
  links.last.is_a?(Chain::Constant)
end

#define(api_map, name_pin, locals) ⇒ ::Array<Pin::Base>

Determine potential Pins returned by this chain of words

Parameters:

  • api_map (ApiMap)
  • name_pin (Pin::Closure)

    the surrounding closure pin for the statement represented by this chain for type resolution and method pin lookup.

    For method calls (Chain::Call objects) as the first element in the chain, ‘name_pin.binder’ should return the ComplexType representing the LHS / “self type” of the call.

  • locals (::Enumerable<Pin::LocalVariable>)

    Any local variables / method parameters etc visible by the statement

Returns:

  • (::Array<Pin::Base>)

    Pins representing possible return types of this method.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/solargraph/source/chain.rb', line 92

def define api_map, name_pin, locals
  return [] if undefined?

  # working_pin is the surrounding closure pin for the link
  # being processed, whose #binder method will provide the LHS /
  # 'self type' of the next link (same as the  #return_type method
  # --the type of the result so far).
  #
  # @todo ProxyType uses 'type' for the binder, but '
  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, locals)
    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?Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/solargraph/source/chain.rb', line 150

def defined?
  !undefined?
end

#descObject



169
170
171
# File 'lib/solargraph/source/chain.rb', line 169

def desc
  links.map(&:desc).to_s
end

#infer(api_map, name_pin, locals) ⇒ ComplexType

@sg-ignore

Parameters:

Returns:



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/solargraph/source/chain.rb', line 117

def infer api_map, name_pin, locals
  cache_key = [node, node&.location, links, name_pin&.return_type, locals]
  if @@inference_invalidation_key == api_map.hash
    cached = @@inference_cache[cache_key]
    return cached if cached
  else
    @@inference_invalidation_key = api_map.hash
    @@inference_cache = {}
  end
  out = infer_uncached api_map, name_pin, locals
  logger.debug { "Chain#infer() - caching result - cache_key_hash=#{cache_key.hash}, links.map(&:hash)=#{links.map(&:hash)}, links=#{links}, cache_key.map(&:hash) = #{cache_key.map(&:hash)}, cache_key=#{cache_key}" }
  @@inference_cache[cache_key] = out
end

#infer_uncached(api_map, name_pin, locals) ⇒ ComplexType

Parameters:

Returns:



135
136
137
138
139
# File 'lib/solargraph/source/chain.rb', line 135

def infer_uncached api_map, name_pin, locals
  pins = define(api_map, name_pin, locals)
  type = infer_first_defined(pins, links.last.last_context, api_map, locals)
  maybe_nil(type)
end

#literal?Boolean

Returns:

  • (Boolean)


142
143
144
# File 'lib/solargraph/source/chain.rb', line 142

def literal?
  links.last.is_a?(Chain::Literal)
end

#nullable?Boolean

Returns:

  • (Boolean)


163
164
165
# File 'lib/solargraph/source/chain.rb', line 163

def nullable?
  links.any?(&:nullable?)
end

#splat?Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/solargraph/source/chain.rb', line 159

def splat?
  @splat
end

#to_sObject



173
174
175
# File 'lib/solargraph/source/chain.rb', line 173

def to_s
  desc
end

#undefined?Boolean

Returns:

  • (Boolean)


146
147
148
# File 'lib/solargraph/source/chain.rb', line 146

def undefined?
  links.any?(&:undefined?)
end