An AST node is characterized by a type and a list of children. It is most easily represented by the s-expression {s} such as:
# AST for "if true; 5 end": s(s(:if, s(:var_ref, s(:kw, "true")), s(s(:int, "5")), nil))
The node type is not considered part of the list, only its children. So +ast+ does not refer to the type, but rather the first child (or object). Items that are not AstNode objects can be part of the list, like Strings or Symbols representing names. To return only the AstNode children of the node, use {children}.
List of all known keywords @return [Hash]
Creates a new AST node
@param [Symbol] type the type of node being created @param [Array<AstNode>] arr the child nodes @param [Hash] opts any extra line options @option opts [Fixnum] :line (nil) the line the node starts on in source @option opts [String] :char (nil) the character number the node starts on
in source
@option opts [Fixnum] :listline (nil) a special key like :line but for
list nodes
@option opts [Fixnum] :listchar (nil) a special key like :char but for
list nodes
@option opts [Boolean] :token (nil) whether the node represents a token
# File lib/yard/parser/ruby/ast_node.rb, line 139 def initialize(type, arr, opts = {}) super(arr) self.type = type self.line_range = opts[:line] self.source_range = opts[:char] @fallback_line = opts[:listline] @fallback_source = opts[:listchar] @token = true if opts[:token] end
Finds the node subclass that should be instantiated for a specific node type
@param [Symbol] type the node type to find a subclass for @return [Class] a subclass of AstNode to instantiate the node with.
# File lib/yard/parser/ruby/ast_node.rb, line 105 def self.node_class_for(type) case type when :params ParameterNode when :call, :fcall, :vcall, :command, :command_call MethodCallNode when :if, :elsif, :if_mod, :unless, :unless_mod ConditionalNode else if type.to_s =~ /_ref\Z/ ReferenceNode elsif type.to_s =~ /_literal\Z/ LiteralNode elsif KEYWORDS.has_key?(type) KeywordNode else AstNode end end end
@return [Boolean] whether the node is equal to another by checking
the list and type
@private
# File lib/yard/parser/ruby/ast_node.rb, line 152 def ==(ast) super && type == ast.type end
@return [Boolean] whether the node is a method call
# File lib/yard/parser/ruby/ast_node.rb, line 225 def call? false end
@return [Array<AstNode>] the {AstNode} children inside the node
# File lib/yard/parser/ruby/ast_node.rb, line 184 def children @children ||= select {|e| AstNode === e } end
@return [Boolean] whether the node is a if/elsif/else condition
# File lib/yard/parser/ruby/ast_node.rb, line 230 def condition? false end
@return [String] the filename the node was parsed from
# File lib/yard/parser/ruby/ast_node.rb, line 70 def file return parent.file if parent @file end
@return [String] the first line of source represented by the node.
# File lib/yard/parser/ruby/ast_node.rb, line 247 def first_line full_source.split(/\r?\n/)[line - 1].strip end
@return [String] the full source that the node was parsed from
# File lib/yard/parser/ruby/ast_node.rb, line 76 def full_source return parent.full_source if parent return @full_source if @full_source return IO.read(@file) if file && File.exist?(file) end
@return [Boolean] whether the node has a {line_range} set
# File lib/yard/parser/ruby/ast_node.rb, line 237 def has_line? @line_range ? true : false end
@return [String] inspects the object
# File lib/yard/parser/ruby/ast_node.rb, line 294 def inspect typeinfo = type && type != :list ? ':' + type.to_s + ', ' : '' 's(' + typeinfo + map(&:inspect).join(", ") + ')' end
Searches through the node and all descendants and returns the first node with a type matching any of node_types, otherwise returns the original node (self).
@example Returns the first method definition in a block of code
ast = YARD.parse_string("if true; def x; end end").ast ast.jump(:def) # => s(:def, s(:ident, "x"), s(:params, nil, nil, nil, nil, # nil), s(s(:void_stmt, )))
@example Returns first 'def' or 'class' statement
ast = YARD.parse_string("class X; def y; end end") ast.jump(:def, :class).first # =>
@example If the node types are not present in the AST
ast = YARD.parse("def x; end") ast.jump(:def)
@param [Array<Symbol>] node_types a set of node types to match @return [AstNode] the matching node, if one was found @return [self] if no node was found
# File lib/yard/parser/ruby/ast_node.rb, line 178 def jump(*node_types) traverse {|child| return(child) if node_types.include?(child.type) } self end
@return [Boolean] whether the node is a keyword
# File lib/yard/parser/ruby/ast_node.rb, line 220 def kw? false end
@return [Fixnum] the starting line number of the node
# File lib/yard/parser/ruby/ast_node.rb, line 242 def line line_range && line_range.first end
@return [Range] the line range in {full_source} represented
by the node
# File lib/yard/parser/ruby/ast_node.rb, line 64 def line_range reset_line_info unless @line_range @line_range end
@return [Boolean] whether the node is a literal value
# File lib/yard/parser/ruby/ast_node.rb, line 215 def literal? false end
@return [nil] pretty prints the node
# File lib/yard/parser/ruby/ast_node.rb, line 259 def pretty_print(q) objs = self.dup + [:__last__] objs.unshift(type) if type && type != :list options = [] if @docstring options << ['docstring', docstring] end if @source_range || @line_range options << ['line', line_range] options << ['source', source_range] end objs.pop if options.size == 0 q.group(3, 's(', ')') do q.seplist(objs, nil, :each) do |v| if v == :__last__ q.seplist(options, nil, :each) do |arr| k, v2 = *arr q.group(3) do q.text k q.group(3) do q.text ': ' q.pp v2 end end end else q.pp v end end end end
@return [Boolean] whether the node is a reference (variable,
constant name)
# File lib/yard/parser/ruby/ast_node.rb, line 210 def ref? false end
@return [String] the first line of source the node represents
# File lib/yard/parser/ruby/ast_node.rb, line 254 def show "\t#{line}: #{first_line}" end
@return [Range] the character range in {full_source} represented
by the node
# File lib/yard/parser/ruby/ast_node.rb, line 57 def source_range reset_line_info unless @source_range @source_range end
@return [Boolean] whether the node is a token
# File lib/yard/parser/ruby/ast_node.rb, line 204 def token? @token end
Traverses the object and yields each node (including descendants) in order.
@yield each descendant node in order @yieldparam [AstNode] self, or a child/descendant node @return [void]
# File lib/yard/parser/ruby/ast_node.rb, line 193 def traverse nodes = [self] nodes.each.with_index do |node, index| yield node nodes.insert index+1, *node.children end end
Generated with the Darkfish Rdoc Generator 2.