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

Inherits:
Array
  • Object
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+ 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

KEYWORDS =

List of all known keywords

Returns:

{ :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)

Creating an AstNode (collapse)

Traversing a Node (collapse)

Node Meta Types (collapse)

Getting Line Information (collapse)

Printing a Node (collapse)

Managing node state (collapse)

Instance Method Summary (collapse)

Constructor Details

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

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



152
153
154
155
156
157
158
159
160
# File 'lib/yard/parser/ruby/ast_node.rb', line 152

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

Instance Attribute Details

- (Object) docstring Also known as: comments

Returns the value of attribute docstring



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

def docstring
  @docstring
end

- (Object) docstring_hash_flag Also known as: comments_hash_flag

Returns the value of attribute docstring_hash_flag



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

def docstring_hash_flag
  @docstring_hash_flag
end

- (Object) docstring_range Also known as: comments_range

Returns the value of attribute docstring_range



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

def docstring_range
  @docstring_range
end

- (String) file

Returns the filename the node was parsed from

Returns:

  • (String)

    the filename the node was parsed from



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

def file
  return parent.file if parent
  @file
end

- (String) full_source

Returns the full source that the node was parsed from

Returns:

  • (String)

    the full source that the node was parsed from



81
82
83
84
85
# File 'lib/yard/parser/ruby/ast_node.rb', line 81

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

- (Object) group

Deprecated.

Groups are now defined by directives



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

def group
  @group
end

- (Range) line_range

Returns the line range in #full_source represented by the node

Returns:

  • (Range)

    the line range in #full_source represented by the node



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

def line_range
  reset_line_info unless @line_range
  @line_range
end

- (AstNode?) parent

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.



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

def parent
  @parent
end

- (String) source

Returns the parse of #full_source that the node represents

Returns:



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

def source
  @source
end

- (Range) source_range

Returns the character range in #full_source represented by the node

Returns:

  • (Range)

    the character range in #full_source represented by the node



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

def source_range
  reset_line_info unless @source_range
  @source_range
end

- (Symbol) type

Returns the node’s unique symbolic type

Returns:

  • (Symbol)

    the node’s unique symbolic type



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

def type
  @type
end

Class Method Details

+ (Class) node_class_for(type)

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.



110
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
# File 'lib/yard/parser/ruby/ast_node.rb', line 110

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.has_key?(type)
      KeywordNode
    else
      AstNode
    end
  end
end

Instance Method Details

- (Boolean) block?

Returns whether the node has a block

Returns:

  • (Boolean)

    whether the node has a block



258
259
260
# File 'lib/yard/parser/ruby/ast_node.rb', line 258

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

- (Boolean) call?

Returns whether the node is a method call

Returns:

  • (Boolean)

    whether the node is a method call



238
239
240
# File 'lib/yard/parser/ruby/ast_node.rb', line 238

def call?
  false
end

- (Array<AstNode>) children

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

Returns:



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

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

- (Boolean) condition?

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

Returns:

  • (Boolean)

    whether the node is a if/elsif/else condition



248
249
250
# File 'lib/yard/parser/ruby/ast_node.rb', line 248

def condition?
  false
end

- (Boolean) def?

Returns whether the node is a method definition

Returns:

  • (Boolean)

    whether the node is a method definition



243
244
245
# File 'lib/yard/parser/ruby/ast_node.rb', line 243

def def?
  false
end

- (String) first_line

Returns the first line of source represented by the node.

Returns:

  • (String)

    the first line of source represented by the node.



275
276
277
# File 'lib/yard/parser/ruby/ast_node.rb', line 275

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

- (Boolean) has_line?

Returns whether the node has a #line_range set

Returns:



265
266
267
# File 'lib/yard/parser/ruby/ast_node.rb', line 265

def has_line?
  @line_range ? true : false
end

- (String) inspect

Returns inspects the object

Returns:

  • (String)

    inspects the object



322
323
324
325
# File 'lib/yard/parser/ruby/ast_node.rb', line 322

def inspect
  typeinfo = type && type != :list ? ':' + type.to_s + ', ' : ''
  's(' + typeinfo + map(&:inspect).join(", ") + ')'
end

- (AstNode, self) jump(*node_types)

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



191
192
193
194
# File 'lib/yard/parser/ruby/ast_node.rb', line 191

def jump(*node_types)
  traverse {|child| return(child) if node_types.include?(child.type) }
  self
end

- (Boolean) kw?

Returns whether the node is a keyword

Returns:

  • (Boolean)

    whether the node is a keyword



233
234
235
# File 'lib/yard/parser/ruby/ast_node.rb', line 233

def kw?
  false
end

- (Fixnum) line

Returns the starting line number of the node

Returns:

  • (Fixnum)

    the starting line number of the node



270
271
272
# File 'lib/yard/parser/ruby/ast_node.rb', line 270

def line
  line_range && line_range.first
end

- (Boolean) literal?

Returns whether the node is a literal value

Returns:

  • (Boolean)

    whether the node is a literal value



228
229
230
# File 'lib/yard/parser/ruby/ast_node.rb', line 228

def literal?
  false
end

- (Boolean) loop?

Returns whether the node is a loop

Returns:

  • (Boolean)

    whether the node is a loop



253
254
255
# File 'lib/yard/parser/ruby/ast_node.rb', line 253

def loop?
  false
end

- (nil) pretty_print(q)

Returns pretty prints the node

Returns:

  • (nil)

    pretty prints the node



287
288
289
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
# File 'lib/yard/parser/ruby/ast_node.rb', line 287

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

- (Boolean) ref?

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

Returns:

  • (Boolean)

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



223
224
225
# File 'lib/yard/parser/ruby/ast_node.rb', line 223

def ref?
  false
end

- (String) show

Returns the first line of source the node represents

Returns:

  • (String)

    the first line of source the node represents



282
283
284
# File 'lib/yard/parser/ruby/ast_node.rb', line 282

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

- (Object) to_s

Returns the value of attribute source



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

def source
  @source
end

- (Boolean) token?

Returns whether the node is a token

Returns:

  • (Boolean)

    whether the node is a token



217
218
219
# File 'lib/yard/parser/ruby/ast_node.rb', line 217

def token?
  @token
end

- (void) traverse {|self,| ... }

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



206
207
208
209
210
211
212
# File 'lib/yard/parser/ruby/ast_node.rb', line 206

def traverse
  nodes = [self]
  nodes.each.with_index do |node, index|
    yield node
    nodes.insert index+1, *node.children
  end
end

- (Object) unfreeze

Resets node state in tree



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

def unfreeze
  @children = nil
end