# Class: YARD::Parser::Ruby::AstNode

Inherits:
  Array
  - Object
  - Array
  - YARD::Parser::Ruby::AstNode
  show all

Defined in:
  lib/yard/parser/ruby/ast_node.rb

## Overview

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.

## Direct Known Subclasses

CommentNode, KeywordNode, LiteralNode, MethodCallNode, MethodDefinitionNode, ParameterNode, ReferenceNode

## Constant Summary collapse

KEYWORDS =

List of all known keywords

Returns:

- (`Hash`)

      {:class => true, :alias => true, :lambda => true, :do_block => true,
      :def => true, :defs => true, :begin => true, :rescue => true, :rescue_mod => true,
      :if => true, :if_mod => true, :else => true, :elsif => true, :case => true,
      :when => true, :next => true, :break => true, :retry => true, :redo => true,
      :return => true, :throw => true, :catch => true, :until => true, :until_mod => true,
      :while => true, :while_mod => true, :yield => true, :yield0 => true, :zsuper => true,
      :unless => true, :unless_mod => true, :for => true, :super => true, :return0 => true}

## Instance Attribute Summary collapse

- #docstring ⇒ Object (also: #comments)

  Returns the value of attribute docstring.

- #docstring_hash_flag ⇒ Object (also: #comments_hash_flag)

  Returns the value of attribute docstring_hash_flag.

- #docstring_range ⇒ Object (also: #comments_range)

  Returns the value of attribute docstring_range.

- #file ⇒ String

  The filename the node was parsed from.

- #full_source ⇒ String

  The full source that the node was parsed from.

- #group ⇒ Object deprecated Deprecated.

  Groups are now defined by directives

- #line_range ⇒ Range

  The line range in #full_source represented by the node.

- #parent ⇒ AstNode?

  The node’s parent or nil if it is a root node.

- #source ⇒ String

  The parse of #full_source that the node represents.

- #source_range ⇒ Range

  The character range in #full_source represented by the node.

- #type ⇒ Symbol

  The node’s unique symbolic type.

## Creating an AstNode collapse

- .node_class_for(type) ⇒ Class

  Finds the node subclass that should be instantiated for a specific node type.

- #initialize(type, arr, opts = {}) ⇒ AstNode constructor

  Creates a new AST node.

## Traversing a Node collapse

- #children ⇒ Array<AstNode>

  The AstNode children inside the node.

- #jump(*node_types) ⇒ AstNode, self

  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).

- #traverse {|self,| ... } ⇒ void

  Traverses the object and yields each node (including descendants) in order.

## Node Meta Types collapse

- #block? ⇒ Boolean

  Whether the node has a block.

- #call? ⇒ Boolean

  Whether the node is a method call.

- #condition? ⇒ Boolean

  Whether the node is a if/elsif/else condition.

- #def? ⇒ Boolean

  Whether the node is a method definition.

- #kw? ⇒ Boolean

  Whether the node is a keyword.

- #literal? ⇒ Boolean

  Whether the node is a literal value.

- #loop? ⇒ Boolean

  Whether the node is a loop.

- #ref? ⇒ Boolean

  Whether the node is a reference (variable, constant name).

- #token? ⇒ Boolean

  Whether the node is a token.

## Getting Line Information collapse

- #first_line ⇒ String

  The first line of source represented by the node.

- #has_line? ⇒ Boolean

  Whether the node has a #line_range set.

- #line ⇒ Fixnum

  The starting line number of the node.

## Printing a Node collapse

- #inspect ⇒ String

  Inspects the object.

- #pretty_print(q) ⇒ nil

  Pretty prints the node.

- #show ⇒ String

  The first line of source the node represents.

## Managing node state collapse

- #unfreeze ⇒ Object

  Resets node state in tree.

## Instance Method Summary collapse

- #to_s ⇒ Object

  Returns the value of attribute source.

## Constructor Details

### #initialize(type, arr, opts = {}) ⇒ `AstNode`

Creates a new AST node

Parameters:

- type (`Symbol`) —

  the type of node being created

- arr (`Array<AstNode>`) —

  the child nodes

- opts (`Hash`) (defaults to: `{}`) —

  any extra line options

Options Hash (`opts`):

- :line (`Fixnum`) — default: `nil` —

  the line the node starts on in source

- :char (`String`) — default: `nil` —

  the character number the node starts on in source

- :listline (`Fixnum`) — default: `nil` —

  a special key like :line but for list nodes

- :listchar (`Fixnum`) — default: `nil` —

  a special key like :char but for list nodes

- :token (`Boolean`) — default: `nil` —

  whether the node represents a token

    153
    154
    155
    156
    157
    158
    159
    160
    161
    162

    # 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

## Instance Attribute Details

### #docstring ⇒ `Object` Also known as: comments

Returns the value of attribute docstring.

    43
    44
    45

    # File 'lib/yard/parser/ruby/ast_node.rb', line 43

    def docstring
      @docstring
    end

### #docstring_hash_flag ⇒ `Object` Also known as: comments_hash_flag

Returns the value of attribute docstring_hash_flag.

    42
    43
    44

    # File 'lib/yard/parser/ruby/ast_node.rb', line 42

    def docstring_hash_flag
      @docstring_hash_flag
    end

### #docstring_range ⇒ `Object` Also known as: comments_range

Returns the value of attribute docstring_range.

    43
    44
    45

    # File 'lib/yard/parser/ruby/ast_node.rb', line 43

    def docstring_range
      @docstring_range
    end

### #file ⇒ `String`

Returns the filename the node was parsed from.

Returns:

- (`String`) —

  the filename the node was parsed from

    76
    77
    78
    79

    # File 'lib/yard/parser/ruby/ast_node.rb', line 76

    def file
      return parent.file if parent
      @file
    end

### #full_source ⇒ `String`

Returns the full source that the node was parsed from.

Returns:

- (`String`) —

  the full source that the node was parsed from

    82
    83
    84
    85
    86

    # 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

### #group ⇒ `Object`

Deprecated.

Groups are now defined by directives

See Also:

- Tags::GroupDirective

    47
    48
    49

    # File 'lib/yard/parser/ruby/ast_node.rb', line 47

    def group
      @group
    end

### #line_range ⇒ `Range`

Returns the line range in #full_source represented by the node.

Returns:

- (`Range`) —

  the line range in #full_source represented by the node

    70
    71
    72
    73

    # File 'lib/yard/parser/ruby/ast_node.rb', line 70

    def line_range
      reset_line_info unless @line_range
      @line_range
    end

### #parent ⇒ `AstNode`?

Returns the node’s parent or nil if it is a root node.

Returns:

- (`AstNode`, `nil`) —

  the node’s parent or nil if it is a root node.

    59
    60
    61

    # File 'lib/yard/parser/ruby/ast_node.rb', line 59

    def parent
      @parent
    end

### #source ⇒ `String`

Returns the parse of #full_source that the node represents.

Returns:

- (`String`) —

  the parse of #full_source that the node represents

    89
    90
    91

    # File 'lib/yard/parser/ruby/ast_node.rb', line 89

    def source
      @source
    end

### #source_range ⇒ `Range`

Returns the character range in #full_source represented by the node.

Returns:

- (`Range`) —

  the character range in #full_source represented by the node

    63
    64
    65
    66

    # File 'lib/yard/parser/ruby/ast_node.rb', line 63

    def source_range
      reset_line_info unless @source_range
      @source_range
    end

### #type ⇒ `Symbol`

Returns the node’s unique symbolic type.

Returns:

- (`Symbol`) —

  the node’s unique symbolic type

    56
    57
    58

    # File 'lib/yard/parser/ruby/ast_node.rb', line 56

    def type
      @type
    end

## Class Method Details

### .node_class_for(type) ⇒ `Class`

Finds the node subclass that should be instantiated for a specific node type

Parameters:

- type (`Symbol`) —

  the node type to find a subclass for

Returns:

- (`Class`) —

  a subclass of AstNode to instantiate the node with.

    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138

    # 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

## Instance Method Details

### #block? ⇒ `Boolean`

Returns whether the node has a block.

Returns:

- (`Boolean`) —

  whether the node has a block

    261
    262
    263

    # File 'lib/yard/parser/ruby/ast_node.rb', line 261

    def block?
      respond_to?(:block) || condition?
    end

### #call? ⇒ `Boolean`

Returns whether the node is a method call.

Returns:

- (`Boolean`) —

  whether the node is a method call

    241
    242
    243

    # File 'lib/yard/parser/ruby/ast_node.rb', line 241

    def call?
      false
    end

### #children ⇒ `Array<AstNode>`

Returns the YARD::Parser::Ruby::AstNode children inside the node.

Returns:

- (`Array<AstNode>`) —

  the YARD::Parser::Ruby::AstNode children inside the node

    199
    200
    201

    # File 'lib/yard/parser/ruby/ast_node.rb', line 199

    def children
      @children ||= select {|e| AstNode === e }
    end

### #condition? ⇒ `Boolean`

Returns whether the node is a if/elsif/else condition.

Returns:

- (`Boolean`) —

  whether the node is a if/elsif/else condition

    251
    252
    253

    # File 'lib/yard/parser/ruby/ast_node.rb', line 251

    def condition?
      false
    end

### #def? ⇒ `Boolean`

Returns whether the node is a method definition.

Returns:

- (`Boolean`) —

  whether the node is a method definition

    246
    247
    248

    # File 'lib/yard/parser/ruby/ast_node.rb', line 246

    def def?
      false
    end

### #first_line ⇒ `String`

Returns the first line of source represented by the node.

Returns:

- (`String`) —

  the first line of source represented by the node.

    278
    279
    280

    # File 'lib/yard/parser/ruby/ast_node.rb', line 278

    def first_line
      full_source.split(/\r?\n/)[line - 1].strip
    end

### #has_line? ⇒ `Boolean`

Returns whether the node has a #line_range set.

Returns:

- (`Boolean`) —

  whether the node has a #line_range set

    268
    269
    270

    # File 'lib/yard/parser/ruby/ast_node.rb', line 268

    def has_line?
      @line_range ? true : false
    end

### #inspect ⇒ `String`

Returns inspects the object.

Returns:

- (`String`) —

  inspects the object

    323
    324
    325
    326

    # 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

### #jump(*node_types) ⇒ `AstNode`, `self`

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).

#### Examples:

#####

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, )))

#####

Returns first ‘def’ or ‘class’ statement

    ast = YARD.parse_string("class X; def y; end end")
    ast.jump(:def, :class).first
    # =>

#####

If the node types are not present in the AST

    ast = YARD.parse("def x; end")
    ast.jump(:def)

Parameters:

- node_types (`Array<Symbol>`) —

  a set of node types to match

Returns:

- (`AstNode`) —

  the matching node, if one was found

- (`self`) —

  if no node was found

    193
    194
    195
    196

    # 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

### #kw? ⇒ `Boolean`

Returns whether the node is a keyword.

Returns:

- (`Boolean`) —

  whether the node is a keyword

    236
    237
    238

    # File 'lib/yard/parser/ruby/ast_node.rb', line 236

    def kw?
      false
    end

### #line ⇒ `Fixnum`

Returns the starting line number of the node.

Returns:

- (`Fixnum`) —

  the starting line number of the node

    273
    274
    275

    # File 'lib/yard/parser/ruby/ast_node.rb', line 273

    def line
      line_range && (line_range.begin || line_range.end)
    end

### #literal? ⇒ `Boolean`

Returns whether the node is a literal value.

Returns:

- (`Boolean`) —

  whether the node is a literal value

    231
    232
    233

    # File 'lib/yard/parser/ruby/ast_node.rb', line 231

    def literal?
      false
    end

### #loop? ⇒ `Boolean`

Returns whether the node is a loop.

Returns:

- (`Boolean`) —

  whether the node is a loop

    256
    257
    258

    # File 'lib/yard/parser/ruby/ast_node.rb', line 256

    def loop?
      false
    end

### #pretty_print(q) ⇒ `nil`

Returns pretty prints the node.

Returns:

- (`nil`) —

  pretty prints the node

    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320

    # 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

### #ref? ⇒ `Boolean`

Returns whether the node is a reference (variable, constant name).

Returns:

- (`Boolean`) —

  whether the node is a reference (variable, constant name)

    226
    227
    228

    # File 'lib/yard/parser/ruby/ast_node.rb', line 226

    def ref?
      false
    end

### #show ⇒ `String`

Returns the first line of source the node represents.

Returns:

- (`String`) —

  the first line of source the node represents

    285
    286
    287

    # File 'lib/yard/parser/ruby/ast_node.rb', line 285

    def show
      "\t#{line}: #{first_line}"
    end

### #to_s ⇒ `Object`

Returns the value of attribute source.

    53
    54
    55

    # File 'lib/yard/parser/ruby/ast_node.rb', line 53

    def source
      @source
    end

### #token? ⇒ `Boolean`

Returns whether the node is a token.

Returns:

- (`Boolean`) —

  whether the node is a token

    220
    221
    222

    # File 'lib/yard/parser/ruby/ast_node.rb', line 220

    def token?
      @token
    end

### #traverse {|self,| ... } ⇒ `void`

This method returns an undefined value.

Traverses the object and yields each node (including descendants) in order.

Yields:

- each descendant node in order

Yield Parameters:

- self, (`AstNode`) —

  or a child/descendant node

    208
    209
    210
    211
    212
    213
    214
    215

    # 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

### #unfreeze ⇒ `Object`

Resets node state in tree

    331
    332
    333

    # File 'lib/yard/parser/ruby/ast_node.rb', line 331

    def unfreeze
      @children = nil
    end