class Solargraph::Parser::ParserGem::NodeChainer
A factory for generating chains from nodes.
Constants
- Chain
Public Class Methods
Source
# File lib/solargraph/parser/parser_gem/node_chainer.rb, line 33 def chain node, filename = nil, parent = nil NodeChainer.new(node, filename, parent).chain end
@param node [Parser::AST::Node] @param filename [String, nil] @param parent [Parser::AST::Node, nil] @return [Source::Chain]
Source
# File lib/solargraph/parser/parser_gem/node_chainer.rb, line 39 def load_string(code) node = Parser.parse(code.sub(/\.$/, '')) chain = NodeChainer.new(node).chain chain.links.push(Chain::Link.new) if code.end_with?('.') chain end
@param code [String] @return [Source::Chain]
Source
# File lib/solargraph/parser/parser_gem/node_chainer.rb, line 16 def initialize node, filename = nil, parent = nil @node = node @filename = filename @parent = parent end
@param node [Parser::AST::Node] @param filename [String, nil] @param parent [Parser::AST::Node, nil]
Public Instance Methods
Source
# File lib/solargraph/parser/parser_gem/node_chainer.rb, line 23 def chain links = generate_links(@node) Chain.new(links, @node, (Parser.is_ast_node?(@node) && @node.type == :splat)) end
@return [Source::Chain]
Private Instance Methods
Source
# File lib/solargraph/parser/parser_gem/node_chainer.rb, line 51 def generate_links n return [] unless n.is_a?(::Parser::AST::Node) return generate_links(n.children[0]) if n.type == :splat # @type [Array<Chain::Link>] result = [] if n.type == :block result.concat NodeChainer.chain(n.children[0], @filename, n).links elsif n.type == :send if n.children[0].is_a?(::Parser::AST::Node) result.concat generate_links(n.children[0]) result.push Chain::Call.new(n.children[1].to_s, Location.from_node(n), node_args(n), passed_block(n)) elsif n.children[0].nil? args = [] n.children[2..-1].each do |c| args.push NodeChainer.chain(c, @filename, n) end result.push Chain::Call.new(n.children[1].to_s, Location.from_node(n), node_args(n), passed_block(n)) else raise "No idea what to do with #{n}" end elsif n.type == :csend if n.children[0].is_a?(::Parser::AST::Node) result.concat generate_links(n.children[0]) result.push Chain::QCall.new(n.children[1].to_s, Location.from_node(n), node_args(n)) elsif n.children[0].nil? result.push Chain::QCall.new(n.children[1].to_s, Location.from_node(n), node_args(n)) else raise "No idea what to do with #{n}" end elsif n.type == :self result.push Chain::Head.new('self') elsif n.type == :zsuper result.push Chain::ZSuper.new('super') elsif n.type == :super args = n.children.map { |c| NodeChainer.chain(c, @filename, n) } result.push Chain::Call.new('super', Location.from_node(n), args) elsif n.type == :yield args = n.children.map { |c| NodeChainer.chain(c, @filename, n) } result.push Chain::Call.new('yield', Location.from_node(n), args) elsif n.type == :const const = unpack_name(n) result.push Chain::Constant.new(const) elsif [:lvar, :lvasgn].include?(n.type) result.push Chain::Call.new(n.children[0].to_s, Location.from_node(n)) elsif [:ivar, :ivasgn].include?(n.type) result.push Chain::InstanceVariable.new(n.children[0].to_s) elsif [:cvar, :cvasgn].include?(n.type) result.push Chain::ClassVariable.new(n.children[0].to_s) elsif [:gvar, :gvasgn].include?(n.type) result.push Chain::GlobalVariable.new(n.children[0].to_s) elsif n.type == :or_asgn new_node = n.updated(n.children[0].type, n.children[0].children + [n.children[1]]) result.concat generate_links new_node elsif [:class, :module, :def, :defs].include?(n.type) # @todo Undefined or what? result.push Chain::UNDEFINED_CALL elsif n.type == :and result.concat generate_links(n.children.last) elsif n.type == :or result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename, n)]) elsif n.type == :if result.push Chain::If.new([NodeChainer.chain(n.children[1], @filename), NodeChainer.chain(n.children[2], @filename, n)]) elsif [:begin, :kwbegin].include?(n.type) result.concat generate_links(n.children.last) elsif n.type == :block_pass block_variable_name_node = n.children[0] if block_variable_name_node.nil? # anonymous block forwarding (e.g., "&") # added in Ruby 3.1 - https://bugs.ruby-lang.org/issues/11256 result.push Chain::BlockVariable.new(nil) else if block_variable_name_node.type == :sym result.push Chain::BlockSymbol.new("#{block_variable_name_node.children[0].to_s}") else result.push Chain::BlockVariable.new("&#{block_variable_name_node.children[0].to_s}") end end elsif n.type == :hash result.push Chain::Hash.new('::Hash', n, hash_is_splatted?(n)) elsif n.type == :array chained_children = n.children.map { |c| NodeChainer.chain(c) } result.push Source::Chain::Array.new(chained_children, n) else lit = infer_literal_node_type(n) result.push (lit ? Chain::Literal.new(lit, n) : Chain::Link.new) end result end
@param n [Parser::AST::Node] @return [Array<Chain::Link>]
Source
# File lib/solargraph/parser/parser_gem/node_chainer.rb, line 141 def hash_is_splatted? node return false unless Parser.is_ast_node?(node) && node.type == :hash return false unless Parser.is_ast_node?(node.children.last) && node.children.last.type == :kwsplat return false if Parser.is_ast_node?(node.children.last.children[0]) && node.children.last.children[0].type == :hash true end
@param node [Parser::AST::Node]
Source
# File lib/solargraph/parser/parser_gem/node_chainer.rb, line 158 def node_args node node.children[2..-1].map do |child| NodeChainer.chain(child, @filename, node) end end
@param node [Parser::AST::Node] @return [Array<Source::Chain>]
Source
# File lib/solargraph/parser/parser_gem/node_chainer.rb, line 150 def passed_block node return unless node == @node && @parent&.type == :block NodeChainer.chain(@parent.children[2], @filename) end
@param node [Parser::AST::Node] @return [Source::Chain, nil]