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.

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 collapse

Creating an AstNode collapse

Traversing a Node collapse

Node Meta Types collapse

Getting Line Information collapse

Printing a Node collapse

Instance Method Summary collapse

Methods inherited from Array

#place

Constructor Details

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

Creates a new AST node

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



139
140
141
142
143
144
145
146
147
# 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

Instance Attribute Details

#docstringObject 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

#docstring_hash_flagObject 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

#docstring_rangeObject 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

#fileString



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

def file
  return parent.file if parent
  @file
end

#full_sourceString



76
77
78
79
80
# 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

#groupObject

Returns the value of attribute group



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

def group
  @group
end

#line_rangeRange



64
65
66
67
# File 'lib/yard/parser/ruby/ast_node.rb', line 64

def line_range
  reset_line_info unless @line_range
  @line_range
end

#parentAstNode?



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

def parent
  @parent
end

#sourceString



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

def source
  @source
end

#source_rangeRange



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

def source_range
  reset_line_info unless @source_range
  @source_range
end

#typeSymbol



50
51
52
# File 'lib/yard/parser/ruby/ast_node.rb', line 50

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



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 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

Instance Method Details

#call?Boolean



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

def call?
  false
end

#childrenArray<AstNode>



184
185
186
# File 'lib/yard/parser/ruby/ast_node.rb', line 184

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

#condition?Boolean



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

def condition?
  false
end

#first_lineString



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

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

#has_line?Boolean



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

def has_line?
  @line_range ? true : false
end

#inspectString



294
295
296
297
# 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

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


178
179
180
181
# 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

#kw?Boolean



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

def kw?
  false
end

#lineFixnum



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

def line
  line_range && line_range.first
end

#literal?Boolean



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

def literal?
  false
end

#pretty_print(q) ⇒ nil



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# 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

#ref?Boolean



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

def ref?
  false
end

#showString



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

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

#to_sObject

Returns the value of attribute source



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

def source
  @source
end

#token?Boolean



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

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



193
194
195
196
197
198
199
# 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