class YARD::Parser::Ruby::AstNode
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[0]
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}.
Constants
- KEYWORDS
-
List of all known keywords @return [Hash]
Attributes
@deprecated Groups are now defined by directives @see Tags::GroupDirective
@return [AstNode, nil] the node’s parent or nil if it is a root node.
@return [Symbol] the node’s unique symbolic type
Public Class Methods
Source
# File lib/yard/parser/ruby/ast_node.rb, line 153 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] @docstring = nil end
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
Source
# File lib/yard/parser/ruby/ast_node.rb, line 111 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 when :for, :while, :while_mod, :until, :until_mod LoopNode when :def, :defs MethodDefinitionNode when :class, :sclass ClassNode when :module ModuleNode else if type.to_s =~ /_ref\Z/ ReferenceNode elsif type.to_s =~ /_literal\Z/ LiteralNode elsif KEYWORDS.key?(type) KeywordNode else AstNode end end 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.
Public Instance Methods
Source
# File lib/yard/parser/ruby/ast_node.rb, line 167 def ==(other) super && type == other.type end
@return [Boolean] whether the node is equal to another by checking
the list and type
@private
Source
# File lib/yard/parser/ruby/ast_node.rb, line 261 def block? respond_to?(:block) || condition? end
@return [Boolean] whether the node has a block
Source
# File lib/yard/parser/ruby/ast_node.rb, line 241 def call? false end
@return [Boolean] whether the node is a method call
Source
# File lib/yard/parser/ruby/ast_node.rb, line 199 def children @children ||= select {|e| AstNode === e } end
@return [Array<AstNode>] the {AstNode} children inside the node
Source
# File lib/yard/parser/ruby/ast_node.rb, line 251 def condition? false end
@return [Boolean] whether the node is a if/elsif/else condition
Source
# File lib/yard/parser/ruby/ast_node.rb, line 246 def def? false end
@return [Boolean] whether the node is a method definition
Source
# File lib/yard/parser/ruby/ast_node.rb, line 76 def file return parent.file if parent @file end
@return [String] the filename the node was parsed from
Source
# File lib/yard/parser/ruby/ast_node.rb, line 278 def first_line full_source.split(/\r?\n/)[line - 1].strip end
@return [String] the first line of source represented by the node.
Source
# File lib/yard/parser/ruby/ast_node.rb, line 82 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 [String] the full source that the node was parsed from
Source
# File lib/yard/parser/ruby/ast_node.rb, line 268 def has_line? @line_range ? true : false end
@return [Boolean] whether the node has a {#line_range} set
Source
# File lib/yard/parser/ruby/ast_node.rb, line 323 def inspect typeinfo = type && type != :list ? ':' + type.to_s + ', ' : '' 's(' + typeinfo + map(&:inspect).join(", ") + ')' end
@return [String] inspects the object
Source
# File lib/yard/parser/ruby/ast_node.rb, line 193 def jump(*node_types) traverse {|child| return(child) if node_types.include?(child.type) } self 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
Source
# File lib/yard/parser/ruby/ast_node.rb, line 236 def kw? false end
@return [Boolean] whether the node is a keyword
Source
# File lib/yard/parser/ruby/ast_node.rb, line 273 def line line_range && line_range.first end
@return [Fixnum] the starting line number of the node
Source
# File lib/yard/parser/ruby/ast_node.rb, line 70 def line_range reset_line_info unless @line_range @line_range end
@return [Range] the line range in {#full_source} represented
by the node
Source
# File lib/yard/parser/ruby/ast_node.rb, line 231 def literal? false end
@return [Boolean] whether the node is a literal value
Source
# File lib/yard/parser/ruby/ast_node.rb, line 256 def loop? false end
@return [Boolean] whether the node is a loop
Source
# File lib/yard/parser/ruby/ast_node.rb, line 290 def pretty_print(q) objs = dup + [:__last__] objs.unshift(type) if type && type != :list options = [] options << ['docstring', docstring] if @docstring if @source_range || @line_range options << ['line', line_range] options << ['source', source_range] end objs.pop if options.empty? 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 [nil] pretty prints the node
Source
# File lib/yard/parser/ruby/ast_node.rb, line 226 def ref? false end
@return [Boolean] whether the node is a reference (variable,
constant name)
Source
# File lib/yard/parser/ruby/ast_node.rb, line 285 def show "\t#{line}: #{first_line}" end
@return [String] the first line of source the node represents
Source
# File lib/yard/parser/ruby/ast_node.rb, line 63 def source_range reset_line_info unless @source_range @source_range end
@return [Range] the character range in {#full_source} represented
by the node
Source
# File lib/yard/parser/ruby/ast_node.rb, line 220 def token? @token end
@return [Boolean] whether the node is a token
Source
# File lib/yard/parser/ruby/ast_node.rb, line 208 def traverse nodes = [self] until nodes.empty? node = nodes.pop yield node nodes += node.children.reverse unless node.children.empty? end 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]
Source
# File lib/yard/parser/ruby/ast_node.rb, line 331 def unfreeze @children = nil end
Resets node state in tree
Private Instance Methods
Source
# File lib/yard/parser/ruby/ast_node.rb, line 341 def reset_line_info if size == 0 self.line_range = @fallback_line self.source_range = @fallback_source elsif !children.empty? f = children.first l = children.last self.line_range = Range.new(f.line_range.first, l.line_range.last) self.source_range = Range.new(f.source_range.first, l.source_range.last) elsif @fallback_line || @fallback_source self.line_range = @fallback_line self.source_range = @fallback_source else self.line_range = 0...0 self.source_range = 0...0 end end
Resets line information @return [void]