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

Constant Summary

KEYWORDS = List of all known keywords.
{ 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

Class Method Summary

Instance Method Summary

Methods inherited from Array

#place

Constructor Details

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

Creates a new AST node

Parameters:

  • (Symbol) type — the type of node being created
  • (Array<AstNode>) arr — the child nodes
  • (Hash) opts (defaults to: {}) — any extra line options

Options Hash (opts):

  • (Fixnum) :line — default: nil — the line the node starts on in source
  • (String) :char — default: nil — the character number the node starts on in source
  • (Fixnum) :listline — default: nil — a special key like :line but for list nodes
  • (Fixnum) :listchar — default: nil — a special key like :char but for list nodes
  • (Boolean) :token — default: nil — whether the node represents a token


90
91
92
93
94
95
96
97
98
# File 'lib/yard/parser/ruby/ast_node.rb', line 90

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



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

def docstring
  @docstring
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

The filename the node was parsed from

Returns:

  • (String) — the filename the node was parsed from


202
203
204
205
# File 'lib/yard/parser/ruby/ast_node.rb', line 202

def file
  return parent.file if parent
  @file
end

- (String) full_source

The full source that the node was parsed from

Returns:

  • (String) — the full source that the node was parsed from


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

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

- (Range) line_range

The line range in #full_source represented by the node

Returns:

  • (Range) — the line range in #full_source represented by the node


120
121
122
123
# File 'lib/yard/parser/ruby/ast_node.rb', line 120

def line_range
  reset_line_info unless @line_range
  @line_range
end

- (Object) parent

Returns the value of attribute parent



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

def parent
  @parent
end

- (String) source Also known as: to_s

The parse of #full_source that the node represents

Returns:



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

def source
  return parent.full_source[source_range] if parent
  full_source
end

- (Range) source_range

The character range in #full_source represented by the node

Returns:

  • (Range) — the character range in #full_source represented by the node


113
114
115
116
# File 'lib/yard/parser/ruby/ast_node.rb', line 113

def source_range
  reset_line_info unless @source_range
  @source_range
end

- (Object) type

Returns the value of attribute type



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

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:

  • (Symbol) type — the node type to find a subclass for

Returns:

  • (Class) — a subclass of AstNode to instantiate the node with.


62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/yard/parser/ruby/ast_node.rb', line 62

def self.node_class_for(type)
  case type
  when :params
    ParameterNode
  when :call, :fcall, :command, :command_call
    MethodCallNode
  when :if, :elsif, :if_mod, :unless, :unless_mod
    ConditionalNode
  when /_ref\Z/
    ReferenceNode
  else
    AstNode
  end
end

Instance Method Details

- (Boolean) ==(ast)

Whether the node is equal to another by checking the list and type

Returns:

  • (Boolean) — whether the node is equal to another by checking the list and type


102
103
104
# File 'lib/yard/parser/ruby/ast_node.rb', line 102

def ==(ast)
  super && type == ast.type
end

- (Boolean) call?

Whether the node is a method call

Returns:

  • (Boolean) — whether the node is a method call


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

def call?
  false
end

- (Array<AstNode>) children

The AstNode children inside the node

Returns:



166
167
168
# File 'lib/yard/parser/ruby/ast_node.rb', line 166

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

- (Object) comments



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

def docstring
  @docstring
end

- (Object) comments_range



44
45
46
# File 'lib/yard/parser/ruby/ast_node.rb', line 44

def docstring_range
  @docstring_range
end

- (Boolean) condition?

Whether the node is a if/elsif/else condition

Returns:

  • (Boolean) — whether the node is a if/elsif/else condition


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

def condition?
  false
end

- (String) first_line

The first line of source represented by the node.

Returns:

  • (String) — the first line of source represented by the node.


136
137
138
# File 'lib/yard/parser/ruby/ast_node.rb', line 136

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

- (Boolean) has_line?

Whether the node has a #line_range set

Returns:



126
127
128
# File 'lib/yard/parser/ruby/ast_node.rb', line 126

def has_line?
  @line_range ? true : false
end

- (String) inspect

Inspects the object

Returns:

  • (String) — inspects the object


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

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 descendents 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:

  • (Array<Symbol>) node_types — a set of node types to match

Returns:

  • (AstNode) — the matching node, if one was found
  • (self) — if no node was found


160
161
162
163
# File 'lib/yard/parser/ruby/ast_node.rb', line 160

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

- (Boolean) kw?

Whether the node is a keyword

Returns:

  • (Boolean) — whether the node is a keyword


187
188
189
# File 'lib/yard/parser/ruby/ast_node.rb', line 187

def kw?
  @kw ||= KEYWORDS.has_key?(type)
end

- (Fixnum) line

The starting line number of the node

Returns:

  • (Fixnum) — the starting line number of the node


131
132
133
# File 'lib/yard/parser/ruby/ast_node.rb', line 131

def line
  line_range && line_range.first
end

- (Boolean) literal?

Whether the node is a literal value

Returns:

  • (Boolean) — whether the node is a literal value


182
183
184
# File 'lib/yard/parser/ruby/ast_node.rb', line 182

def literal?
  @literal ||= type =~ /_literal$/ ? true : false
end

- (nil) pretty_print(q)

Pretty prints the node

Returns:

  • (nil) — pretty prints the node


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/yard/parser/ruby/ast_node.rb', line 221

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 |k, v| 
          q.group(3) do 
            q.text k
            q.group(3) do 
              q.text ': '
              q.pp v 
            end
          end
        end
      else
        q.pp v 
      end
    end
  end
end

- (Boolean) ref?

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

Returns:

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


177
178
179
# File 'lib/yard/parser/ruby/ast_node.rb', line 177

def ref?
  false
end

- (String) show

The first line of source the node represents

Returns:

  • (String) — the first line of source the node represents


107
108
109
# File 'lib/yard/parser/ruby/ast_node.rb', line 107

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

- (Object) to_s



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

def source
  @source
end

- (Boolean) token?

Whether the node is a token

Returns:

  • (Boolean) — whether the node is a token


171
172
173
# File 'lib/yard/parser/ruby/ast_node.rb', line 171

def token?
  @token
end

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

This method returns an undefined value.

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

Yields:

  • each descendent node in order

Yield Parameters:

  • (AstNode) self, — or a child/descendent node


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

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