Class: Solargraph::Parser::FlowSensitiveTyping
- Inherits:
-
Object
- Object
- Solargraph::Parser::FlowSensitiveTyping
- Extended by:
- Logging
- Includes:
- Logging, NodeMethods
- Defined in:
- lib/solargraph/parser/flow_sensitive_typing.rb
Constant Summary
Constants included from Logging
Logging::DEFAULT_LOG_LEVEL, Logging::LOG_LEVELS
Class Method Summary collapse
-
.visible_pins(pins, name, closure, location) ⇒ Array<Pin::LocalVariable>
Find a variable pin by name and where it is used.
Instance Method Summary collapse
-
#initialize(locals, enclosing_breakable_pin = nil) ⇒ FlowSensitiveTyping
constructor
A new instance of FlowSensitiveTyping.
- #process_and(and_node, true_ranges = []) ⇒ void
- #process_if(if_node) ⇒ void
Methods included from Logging
Methods included from NodeMethods
any_splatted_call?, call_nodes_from, const_nodes_from, convert_hash, find_recipient_node, get_node_end_position, get_node_start_position, process, returns_from_method_body, unpack_name, value_position_nodes_only
Constructor Details
#initialize(locals, enclosing_breakable_pin = nil) ⇒ FlowSensitiveTyping
Returns a new instance of FlowSensitiveTyping.
8 9 10 11 |
# File 'lib/solargraph/parser/flow_sensitive_typing.rb', line 8 def initialize(locals, enclosing_breakable_pin = nil) @locals = locals @enclosing_breakable_pin = enclosing_breakable_pin end |
Class Method Details
.visible_pins(pins, name, closure, location) ⇒ Array<Pin::LocalVariable>
Find a variable pin by name and where it is used.
Resolves our most specific view of this variable’s type by preferring pins created by flow-sensitive typing when we have them based on the Closure and Location.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/solargraph/parser/flow_sensitive_typing.rb', line 90 def self.visible_pins(pins, name, closure, location) logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location})" } pins_with_name = pins.select { |p| p.name == name } if pins_with_name.empty? logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => [] - no pins with name" } return [] end pins_with_specific_visibility = pins.select { |p| p.name == name && p.presence && p.visible_at?(closure, location) } if pins_with_specific_visibility.empty? logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => #{pins_with_name} - no pins with specific visibility" } return pins_with_name end visible_pins_specific_to_this_closure = pins_with_specific_visibility.select { |p| p.closure == closure } if visible_pins_specific_to_this_closure.empty? logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => #{pins_with_specific_visibility} - no visible pins specific to this closure (#{closure})}" } return pins_with_specific_visibility end flow_defined_pins = pins_with_specific_visibility.select { |p| p.presence_certain? } if flow_defined_pins.empty? logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => #{visible_pins_specific_to_this_closure} - no flow-defined pins" } return visible_pins_specific_to_this_closure end logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location}) => #{flow_defined_pins}" } flow_defined_pins end |
Instance Method Details
#process_and(and_node, true_ranges = []) ⇒ void
This method returns an undefined value.
17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/solargraph/parser/flow_sensitive_typing.rb', line 17 def process_and(and_node, true_ranges = []) # @type [Parser::AST::Node] lhs = and_node.children[0] # @type [Parser::AST::Node] rhs = and_node.children[1] before_rhs_loc = rhs.location.expression.adjust(begin_pos: -1) before_rhs_pos = Position.new(before_rhs_loc.line, before_rhs_loc.column) rhs_presence = Range.new(before_rhs_pos, get_node_end_position(rhs)) process_isa(lhs, true_ranges + [rhs_presence]) end |
#process_if(if_node) ⇒ void
This method returns an undefined value.
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 |
# File 'lib/solargraph/parser/flow_sensitive_typing.rb', line 34 def process_if(if_node) # # See if we can refine a type based on the result of 'if foo.nil?' # # [3] pry(main)> require 'parser/current'; Parser::CurrentRuby.parse("if foo.is_a? Baz; then foo; else bar; end") # => s(:if, # s(:send, # s(:send, nil, :foo), :is_a?, # s(:const, nil, :Baz)), # s(:send, nil, :foo), # s(:send, nil, :bar)) # [4] pry(main)> conditional_node = if_node.children[0] # @type [Parser::AST::Node] then_clause = if_node.children[1] # @type [Parser::AST::Node] else_clause = if_node.children[2] true_ranges = [] if always_breaks?(else_clause) unless enclosing_breakable_pin.nil? rest_of_breakable_body = Range.new(get_node_end_position(if_node), get_node_end_position(enclosing_breakable_pin.node)) true_ranges << rest_of_breakable_body end end unless then_clause.nil? # # Add specialized locals for the then clause range # before_then_clause_loc = then_clause.location.expression.adjust(begin_pos: -1) before_then_clause_pos = Position.new(before_then_clause_loc.line, before_then_clause_loc.column) true_ranges << Range.new(before_then_clause_pos, get_node_end_position(then_clause)) end process_conditional(conditional_node, true_ranges) end |